Add project files.

This commit is contained in:
2022-03-05 12:44:06 +02:00
parent 453a74459f
commit f4f90b2533
517 changed files with 195610 additions and 0 deletions

56
game/CMakeLists.txt Normal file
View File

@ -0,0 +1,56 @@
cmake_minimum_required(VERSION 3.8)
project(game CXX)
file(GLOB_RECURSE sources
src/*.cpp src/*.h
)
include_directories(${PROJECT_BINARY_DIR}/src/system/)
include_directories(src/)
# Find dependencies
find_package(libmysql REQUIRED)
find_package(Boost COMPONENTS system REQUIRED)
find_package(DevIL REQUIRED)
find_package(LZO REQUIRED)
add_executable(${PROJECT_NAME} ${sources})
# Link dependencies if found
if (libmysql_FOUND)
target_link_libraries (${PROJECT_NAME} ${MYSQL_LIBRARIES})
endif (libmysql_FOUND)
if (Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries (${PROJECT_NAME} ${Boost_LIBRARIES} ${Boost_SYSTEM_LIBRARY})
endif (Boost_FOUND)
if (IL_FOUND)
include_directories(${IL_INCLUDE_DIR})
target_link_libraries (${PROJECT_NAME} ${IL_LIBRARIES})
endif (IL_FOUND)
if (LZO_FOUND)
include_directories(${LZO_INCLUDE_DIR})
target_link_libraries (${PROJECT_NAME} ${LZO_LIBRARIES})
endif (LZO_FOUND)
target_link_libraries(${PROJECT_NAME} md)
# Pthreads
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package (Threads REQUIRED)
target_link_libraries (${PROJECT_NAME} Threads::Threads)
find_package(GTest REQUIRED)
if (GTEST_FOUND)
include_directories(${GTEST_INCLUDE_DIRS})
target_link_libraries (${PROJECT_NAME} ${GTEST_BOTH_LIBRARIES})
endif (GTEST_FOUND)
target_link_libraries(${PROJECT_NAME} libgame libpoly libsql libthecore liblua)

335
game/src/BattleArena.cpp Normal file
View File

@ -0,0 +1,335 @@
#include "stdafx.h"
#include "constants.h"
#include "BattleArena.h"
#include "start_position.h"
#include "char_manager.h"
#include "char.h"
#include "sectree_manager.h"
#include "regen.h"
#include "questmanager.h"
extern int passes_per_sec;
extern int test_server;
CBattleArena::CBattleArena()
: m_pEvent(NULL),
m_status(STATUS_CLOSE),
m_nMapIndex(0),
m_nEmpire(0),
m_bForceEnd(false)
{
}
bool CBattleArena::IsRunning()
{
return m_status == STATUS_CLOSE ? false : true;
}
bool CBattleArena::IsBattleArenaMap(int nMapIndex)
{
if ( nMapIndex == nBATTLE_ARENA_MAP[1] ||
nMapIndex == nBATTLE_ARENA_MAP[2] ||
nMapIndex == nBATTLE_ARENA_MAP[3] )
{
return true;
}
return false;
}
struct FWarpToHome
{
void operator() (LPENTITY ent)
{
if ( ent->IsType(ENTITY_CHARACTER) == true )
{
LPCHARACTER lpChar = (LPCHARACTER)ent;
if ( lpChar->IsPC() == true )
{
if ( !test_server )
{
if ( lpChar->GetGMLevel() != GM_PLAYER ) return;
}
int nEmpire, nMapIndex, x, y;
nEmpire = lpChar->GetEmpire();
nMapIndex = EMPIRE_START_MAP(nEmpire);
x = EMPIRE_START_X(nEmpire);
y = EMPIRE_START_Y(nEmpire);
lpChar->WarpSet(x, y, nMapIndex);
}
}
}
};
void CBattleArena::SetStatus(BATTLEARENA_STATUS status)
{
m_status = status;
}
EVENTINFO(SBattleArenaInfo)
{
int nEmpire;
int nMapIndex;
int state;
int wait_count;
SBattleArenaInfo()
: nEmpire( 0 )
, nMapIndex( 0 )
, state( 0 )
, wait_count( 0 )
{
}
};
EVENTFUNC(battle_arena_event)
{
SBattleArenaInfo * pInfo = dynamic_cast<SBattleArenaInfo *>(event->info );
if ( pInfo == NULL )
{
return 0; // cancel immediately
}
if (pInfo != NULL)
{
switch (pInfo->state)
{
case 0:
{
++pInfo->state;
BroadcastNotice(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ݱ<EFBFBD><DDB1><EFBFBD> 5<><35> <20><><EFBFBD>ҽ<EFBFBD><D2BD>ϴ<EFBFBD>!!!"));
}
return test_server ? PASSES_PER_SEC(60) : PASSES_PER_SEC(60*4);
case 1:
{
++pInfo->state;
BroadcastNotice(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ݱ<EFBFBD><DDB1><EFBFBD> 1<><31> <20><><EFBFBD>ҽ<EFBFBD><D2BD>ϴ<EFBFBD>!!!"));
}
return test_server ? PASSES_PER_SEC(10) : PASSES_PER_SEC(60);
case 2:
{
++pInfo->state;
pInfo->wait_count = 0;
quest::CQuestManager::instance().RequestSetEventFlag("battle_arena", 0);
BroadcastNotice(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>߽<EFBFBD><DFBD>ϴ<EFBFBD>."));
LPSECTREE_MAP sectree = SECTREE_MANAGER::instance().GetMap(pInfo->nMapIndex);
if ( sectree != NULL )
{
std::string strMap = LocaleService_GetMapPath();
if ( pInfo->nEmpire > 0 )
{
strMap += strRegen[pInfo->nEmpire];
regen_do(strMap.c_str(), pInfo->nMapIndex, sectree->m_setting.iBaseX, sectree->m_setting.iBaseY, NULL, false);
}
}
}
return test_server ? PASSES_PER_SEC(60*1) : PASSES_PER_SEC(60*5);
case 3 :
{
if ( SECTREE_MANAGER::instance().GetMonsterCountInMap(pInfo->nMapIndex) <= 0 )
{
pInfo->state = 6;
SendNoticeMap(LC_TEXT("<EFBFBD>߾<EFBFBD> <20><><EFBFBD>ܿ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>𿩵<EFBFBD><F0BFA9B5>ϴ<EFBFBD>."), pInfo->nMapIndex, false);
}
else
{
pInfo->wait_count++;
if ( pInfo->wait_count >= 5 )
{
pInfo->state++;
SendNoticeMap(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>Դϴ<D4B4>."), pInfo->nMapIndex, false);
}
else
{
CBattleArena::instance().SpawnRandomStone();
}
}
}
return test_server ? PASSES_PER_SEC(60) : PASSES_PER_SEC(60*5);
case 4 :
{
pInfo->state++;
SendNoticeMap(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>߽<EFBFBD><DFBD>ϴ<EFBFBD>."), pInfo->nMapIndex, false);
SendNoticeMap(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ư<EFBFBD><C6B0>ϴ<EFBFBD>."), pInfo->nMapIndex, false);
SECTREE_MANAGER::instance().PurgeMonstersInMap(pInfo->nMapIndex);
}
return PASSES_PER_SEC(30);
case 5 :
{
LPSECTREE_MAP sectree = SECTREE_MANAGER::instance().GetMap(pInfo->nMapIndex);
if ( sectree != NULL )
{
struct FWarpToHome f;
sectree->for_each( f );
}
CBattleArena::instance().End();
}
return 0;
case 6 :
{
pInfo->state++;
pInfo->wait_count = 0;
SendNoticeMap(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>Ÿ<EFBFBD><C5B8><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."), pInfo->nMapIndex, false);
SendNoticeMap(LC_TEXT("30<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>͸<EFBFBD><CDB8><EFBFBD><EFBFBD>ָ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ּ<EFBFBD><D6BC><EFBFBD>."), pInfo->nMapIndex, false);
CBattleArena::instance().SpawnLastBoss();
}
return test_server ? PASSES_PER_SEC(60) : PASSES_PER_SEC(60*5);
case 7 :
{
if ( SECTREE_MANAGER::instance().GetMonsterCountInMap(pInfo->nMapIndex) <= 0 )
{
SendNoticeMap(LC_TEXT("<EFBFBD>͸<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֿ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD>ϴ<EFBFBD>."), pInfo->nMapIndex, false);
SendNoticeMap(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ư<EFBFBD><C6B0>ϴ<EFBFBD>."), pInfo->nMapIndex, false);
pInfo->state = 5;
return PASSES_PER_SEC(60);
}
pInfo->wait_count++;
if ( pInfo->wait_count >= 6 )
{
SendNoticeMap(LC_TEXT("<EFBFBD>͸<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ְ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD><EFBFBD>ϴ<EFBFBD>."), pInfo->nMapIndex, false);
SendNoticeMap(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ư<EFBFBD><C6B0>ϴ<EFBFBD>."), pInfo->nMapIndex, false);
SECTREE_MANAGER::instance().PurgeMonstersInMap(pInfo->nMapIndex);
SECTREE_MANAGER::instance().PurgeStonesInMap(pInfo->nMapIndex);
pInfo->state = 5;
return PASSES_PER_SEC(60);
}
else
{
CBattleArena::instance().SpawnRandomStone();
}
}
return test_server ? PASSES_PER_SEC(60) : PASSES_PER_SEC(60*5);
}
}
return 0;
}
bool CBattleArena::Start(int nEmpire)
{
if ( m_status != STATUS_CLOSE ) return false;
if ( nEmpire < 1 || nEmpire > 3 ) return false;
m_nMapIndex = nBATTLE_ARENA_MAP[nEmpire];
m_nEmpire = nEmpire;
char szBuf[1024];
snprintf(szBuf, sizeof(szBuf), LC_TEXT("%s<><73> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><CDB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>."), EMPIRE_NAME(m_nEmpire));
BroadcastNotice(szBuf);
BroadcastNotice(LC_TEXT("10<EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Դϴ<D4B4>."));
if (m_pEvent != NULL) {
event_cancel(&m_pEvent);
}
SBattleArenaInfo* info = AllocEventInfo<SBattleArenaInfo>();
info->nMapIndex = m_nMapIndex;
info->nEmpire = m_nEmpire;
info->state = 0;
info->wait_count = 0;
m_pEvent = event_create(battle_arena_event, info, test_server ? PASSES_PER_SEC(60) : PASSES_PER_SEC(5*60));
SetStatus(STATUS_BATTLE);
quest::CQuestManager::instance().RequestSetEventFlag("battle_arena", m_nMapIndex);
return true;
}
void CBattleArena::End()
{
if (m_pEvent != NULL) {
event_cancel(&m_pEvent);
}
m_bForceEnd = false;
m_nMapIndex = 0;
m_nEmpire = 0;
m_status = STATUS_CLOSE;
quest::CQuestManager::instance().RequestSetEventFlag("battle_arena", 0);
}
void CBattleArena::ForceEnd()
{
if ( m_bForceEnd == true ) return;
m_bForceEnd = true;
if (m_pEvent != NULL) {
event_cancel(&m_pEvent);
}
SBattleArenaInfo* info = AllocEventInfo<SBattleArenaInfo>();
info->nMapIndex = m_nMapIndex;
info->nEmpire = m_nEmpire;
info->state = 3;
event_create(battle_arena_event, info, PASSES_PER_SEC(5));
}
void CBattleArena::SpawnRandomStone()
{
static const DWORD vnum[7] = { 8012, 8013, 8014, 8024, 8025, 8026, 8027 };
static const int region_info[3][4] = {
{688900, 247600, 692700, 250000},
{740200, 251000, 744200, 247700},
{791400, 250900, 795900, 250400} };
int idx = m_nMapIndex - 190;
if ( idx < 0 || idx >= 3 ) return;
CHARACTER_MANAGER::instance().SpawnMobRange(
vnum[number(0, 6)],
m_nMapIndex,
region_info[idx][0], region_info[idx][1], region_info[idx][2], region_info[idx][3],
false, true);
}
void CBattleArena::SpawnLastBoss()
{
static const DWORD vnum = 8616;
static const int position[3][2] = {
{ 691000, 248900 },
{ 742300, 249000 },
{ 793600, 249300 } };
int idx = m_nMapIndex - 190;
if ( idx < 0 || idx >= 3 ) return;
CHARACTER_MANAGER::instance().SpawnMob(vnum, m_nMapIndex, position[idx][0], position[idx][1], 0);
}

42
game/src/BattleArena.h Normal file
View File

@ -0,0 +1,42 @@
const static int nBATTLE_ARENA_MAP[] = { 0, 190, 191, 192 };
const static std::string strRegen[] =
{
"",
"/metin2_map_battlearena01/regen00.txt",
"/metin2_map_battlearena02/regen00.txt",
"/metin2_map_battlearena03/regen00.txt",
};
enum BATTLEARENA_STATUS
{
STATUS_CLOSE = 0,
STATUS_BATTLE,
STATUS_END,
};
class CBattleArena : public singleton<CBattleArena>
{
private :
LPEVENT m_pEvent;
BATTLEARENA_STATUS m_status;
int m_nMapIndex;
int m_nEmpire;
bool m_bForceEnd;
public :
CBattleArena();
static bool IsBattleArenaMap(int nMapIndex);
bool IsRunning();
void SetStatus(BATTLEARENA_STATUS status);
bool Start(int nEmpire);
void ForceEnd();
void End();
void SpawnLastBoss();
void SpawnRandomStone();
};

197
game/src/BlueDragon.cpp Normal file
View File

@ -0,0 +1,197 @@
#include "stdafx.h"
#include "BlueDragon.h"
extern int test_server;
extern int passes_per_sec;
#include "vector.h"
#include "utils.h"
#include "char.h"
#include "mob_manager.h"
#include "sectree_manager.h"
#include "battle.h"
#include "affect.h"
#include "BlueDragon_Binder.h"
#include "BlueDragon_Skill.h"
#include "packet.h"
#include "motion.h"
time_t UseBlueDragonSkill(LPCHARACTER pChar, unsigned int idx)
{
LPSECTREE_MAP pSecMap = SECTREE_MANAGER::instance().GetMap( pChar->GetMapIndex() );
if (NULL == pSecMap)
return 0;
int nextUsingTime = 0;
switch (idx)
{
case 0:
{
sys_log(0, "BlueDragon: Using Skill Breath");
FSkillBreath f(pChar);
pSecMap->for_each( f );
nextUsingTime = number(BlueDragon_GetSkillFactor(3, "Skill0", "period", "min"), BlueDragon_GetSkillFactor(3, "Skill0", "period", "max"));
}
break;
case 1:
{
sys_log(0, "BlueDragon: Using Skill Weak Breath");
FSkillWeakBreath f(pChar);
pSecMap->for_each( f );
nextUsingTime = number(BlueDragon_GetSkillFactor(3, "Skill1", "period", "min"), BlueDragon_GetSkillFactor(3, "Skill1", "period", "max"));
}
break;
case 2:
{
sys_log(0, "BlueDragon: Using Skill EarthQuake");
FSkillEarthQuake f(pChar);
pSecMap->for_each( f );
nextUsingTime = number(BlueDragon_GetSkillFactor(3, "Skill2", "period", "min"), BlueDragon_GetSkillFactor(3, "Skill2", "period", "max"));
if (NULL != f.pFarthestChar)
{
pChar->BeginFight( f.pFarthestChar );
}
}
break;
default:
sys_err("BlueDragon: Wrong Skill Index: %d", idx);
return 0;
}
int addPct = BlueDragon_GetRangeFactor("hp_period", pChar->GetHPPct());
nextUsingTime += (nextUsingTime * addPct) / 100;
return nextUsingTime;
}
int BlueDragon_StateBattle(LPCHARACTER pChar)
{
if (pChar->GetHPPct() > 98)
return PASSES_PER_SEC(1);
const int SkillCount = 3;
int SkillPriority[SkillCount];
static time_t timeSkillCanUseTime[SkillCount];
if (pChar->GetHPPct() > 76)
{
SkillPriority[0] = 1;
SkillPriority[1] = 0;
SkillPriority[2] = 2;
}
else if (pChar->GetHPPct() > 31)
{
SkillPriority[0] = 0;
SkillPriority[1] = 1;
SkillPriority[2] = 2;
}
else
{
SkillPriority[0] = 0;
SkillPriority[1] = 2;
SkillPriority[2] = 1;
}
time_t timeNow = static_cast<time_t>(get_dword_time());
for (int i=0 ; i < SkillCount ; ++i)
{
const int SkillIndex = SkillPriority[i];
if (timeSkillCanUseTime[SkillIndex] < timeNow)
{
int SkillUsingDuration =
static_cast<int>(CMotionManager::instance().GetMotionDuration( pChar->GetRaceNum(), MAKE_MOTION_KEY(MOTION_MODE_GENERAL, MOTION_SPECIAL_1 + SkillIndex) ));
timeSkillCanUseTime[SkillIndex] = timeNow + (UseBlueDragonSkill( pChar, SkillIndex ) * 1000) + SkillUsingDuration + 3000;
pChar->SendMovePacket(FUNC_MOB_SKILL, SkillIndex, pChar->GetX(), pChar->GetY(), 0, timeNow);
return 0 == SkillUsingDuration ? PASSES_PER_SEC(1) : PASSES_PER_SEC(SkillUsingDuration);
}
}
return PASSES_PER_SEC(1);
}
int BlueDragon_Damage (LPCHARACTER me, LPCHARACTER pAttacker, int dam)
{
if (NULL == me || NULL == pAttacker)
return dam;
if (true == pAttacker->IsMonster() && 2493 == pAttacker->GetMobTable().dwVnum)
{
for (int i=1 ; i <= 4 ; ++i)
{
if (ATK_BONUS == BlueDragon_GetIndexFactor("DragonStone", i, "effect_type"))
{
DWORD dwDragonStoneID = BlueDragon_GetIndexFactor("DragonStone", i, "vnum");
size_t val = BlueDragon_GetIndexFactor("DragonStone", i, "val");
size_t cnt = SECTREE_MANAGER::instance().GetMonsterCountInMap( pAttacker->GetMapIndex(), dwDragonStoneID );
dam += (dam * (val*cnt))/100;
break;
}
}
}
if (true == me->IsMonster() && 2493 == me->GetMobTable().dwVnum)
{
for (int i=1 ; i <= 4 ; ++i)
{
if (DEF_BONUS == BlueDragon_GetIndexFactor("DragonStone", i, "effect_type"))
{
DWORD dwDragonStoneID = BlueDragon_GetIndexFactor("DragonStone", i, "vnum");
size_t val = BlueDragon_GetIndexFactor("DragonStone", i, "val");
size_t cnt = SECTREE_MANAGER::instance().GetMonsterCountInMap( me->GetMapIndex(), dwDragonStoneID );
dam -= (dam * (val*cnt))/100;
if (dam <= 0)
dam = 1;
break;
}
}
}
if (true == me->IsStone() && 0 != pAttacker->GetMountVnum())
{
for (int i=1 ; i <= 4 ; ++i)
{
if (me->GetMobTable().dwVnum == BlueDragon_GetIndexFactor("DragonStone", i, "vnum"))
{
if (pAttacker->GetMountVnum() == BlueDragon_GetIndexFactor("DragonStone", i, "enemy"))
{
size_t val = BlueDragon_GetIndexFactor("DragonStone", i, "enemy_val");
dam *= val;
break;
}
}
}
}
return dam;
}

5
game/src/BlueDragon.h Normal file
View File

@ -0,0 +1,5 @@
extern int BlueDragon_StateBattle (LPCHARACTER);
extern time_t UseBlueDragonSkill (LPCHARACTER, unsigned int);
extern int BlueDragon_Damage (LPCHARACTER me, LPCHARACTER attacker, int dam);

View File

@ -0,0 +1,218 @@
#include "stdafx.h"
#include "BlueDragon_Binder.h"
#include "questmanager.h"
unsigned int BlueDragon_GetSkillFactor(const size_t cnt, ...)
{
lua_State* L = quest::CQuestManager::instance().GetLuaState();
const int stack_top = lua_gettop(L);
lua_getglobal( L, "BlueDragonSetting" );
if (false == lua_istable(L, -1))
{
lua_settop( L, stack_top );
return 0;
}
va_list vl;
va_start(vl, cnt);
for( size_t i=0 ; i < cnt ; ++i )
{
const char* key = va_arg(vl, const char*);
if (NULL == key)
{
va_end(vl);
lua_settop( L, stack_top );
sys_err("BlueDragon: wrong key list");
return 0;
}
lua_pushstring( L, key );
lua_gettable( L, -2 );
if (false == lua_istable(L, -1) && i != cnt-1)
{
va_end(vl);
lua_settop( L, stack_top );
sys_err("BlueDragon: wrong key table %s", key);
return 0;
}
}
va_end(vl);
if (false == lua_isnumber(L, -1))
{
lua_settop( L, stack_top );
sys_err("BlueDragon: Last key is not a number");
return 0;
}
int val = static_cast<int>(lua_tonumber( L, -1 ));
lua_settop( L, stack_top );
return val;
}
unsigned int BlueDragon_GetRangeFactor(const char* key, const int val)
{
lua_State* L = quest::CQuestManager::instance().GetLuaState();
const int stack_top = lua_gettop(L);
lua_getglobal( L, "BlueDragonSetting" );
if (false == lua_istable(L, -1))
{
lua_settop( L, stack_top );
return 0;
}
lua_pushstring( L, key );
lua_gettable( L, -2 );
if (false == lua_istable(L, -1))
{
lua_settop( L, stack_top );
sys_err("BlueDragon: no required table %s", key);
return 0;
}
const size_t cnt = static_cast<size_t>(luaL_getn(L, -1));
for( size_t i=1 ; i <= cnt ; ++i )
{
lua_rawgeti( L, -1, i );
if (false == lua_istable(L, -1))
{
lua_settop( L, stack_top );
sys_err("BlueDragon: wrong table index %s %d", key, i);
return 0;
}
lua_pushstring( L, "min" );
lua_gettable( L, -2 );
if (false == lua_isnumber(L, -1))
{
lua_settop( L, stack_top );
sys_err("BlueDragon: no min value set %s", key);
return 0;
}
const int min = static_cast<int>(lua_tonumber(L, -1));
lua_pop(L, 1);
lua_pushstring( L, "max" );
lua_gettable( L, -2 );
if (false == lua_isnumber(L, -1))
{
lua_settop( L, stack_top );
sys_err("BlueDragon: no max value set %s", key);
return 0;
}
const int max = static_cast<int>(lua_tonumber(L, -1));
lua_pop(L, 1);
if (min <= val && val <= max)
{
lua_pushstring( L, "pct" );
lua_gettable( L, -2 );
if (false == lua_isnumber(L, -1))
{
lua_settop( L, stack_top );
sys_err("BlueDragon: no pct value set %s", key);
return 0;
}
const int pct = static_cast<int>(lua_tonumber(L, -1));
lua_settop( L, stack_top );
return pct;
}
lua_pop(L, 1);
}
lua_settop( L, stack_top );
return 0;
}
unsigned int BlueDragon_GetIndexFactor(const char* container, const size_t idx, const char* key)
{
lua_State* L = quest::CQuestManager::instance().GetLuaState();
const int stack_top = lua_gettop(L);
lua_getglobal( L, "BlueDragonSetting" );
if (false == lua_istable(L, -1))
{
lua_settop( L, stack_top );
return 0;
}
lua_pushstring( L, container );
lua_gettable( L, -2 );
if (false == lua_istable(L, -1))
{
lua_settop( L, stack_top );
sys_err("BlueDragon: no required table %s", key);
return 0;
}
lua_rawgeti( L, -1, idx );
if (false == lua_istable(L, -1))
{
lua_settop( L, stack_top );
sys_err("BlueDragon: wrong table index %s %d", key, idx);
return 0;
}
lua_pushstring( L, key );
lua_gettable( L, -2 );
if (false == lua_isnumber(L, -1))
{
lua_settop( L, stack_top );
sys_err("BlueDragon: no min value set %s", key);
return 0;
}
const unsigned int ret = static_cast<unsigned int>(lua_tonumber(L, -1));
lua_settop( L, stack_top );
return ret;
}

View File

@ -0,0 +1,13 @@
enum BLUEDRAGON_STONE_EFFECT
{
DEF_BONUS = 1,
ATK_BONUS = 2,
REGEN_TIME_BONUS = 3,
REGEN_PECT_BONUS = 4,
};
extern unsigned int BlueDragon_GetRangeFactor (const char* key, const int val);
extern unsigned int BlueDragon_GetSkillFactor (const size_t cnt, ...);
extern unsigned int BlueDragon_GetIndexFactor (const char* container, const size_t idx, const char* key);

342
game/src/BlueDragon_Skill.h Normal file
View File

@ -0,0 +1,342 @@
struct FSkillBreath
{
EJobs Set1;
EJobs Set2;
ESex gender;
LPCHARACTER pAttacker;
FSkillBreath(LPCHARACTER p)
{
pAttacker = p;
Set1 = static_cast<EJobs>(number(0,3));
Set2 = static_cast<EJobs>(number(0,3));
gender = static_cast<ESex>(number(0,2));
}
void operator()(LPENTITY ent)
{
if (NULL != ent)
{
if (true == ent->IsType(ENTITY_CHARACTER))
{
LPCHARACTER ch = static_cast<LPCHARACTER>(ent);
if (true == ch->IsPC() && false == ch->IsDead())
{
if (NULL != ch->FindAffect(AFFECT_REVIVE_INVISIBLE, APPLY_NONE))
return;
if ((signed)BlueDragon_GetSkillFactor(2, "Skill0", "damage_area") < DISTANCE_APPROX(pAttacker->GetX()-ch->GetX(), pAttacker->GetY()-ch->GetY()))
{
sys_log(0, "BlueDragon: Breath too far (%d)", DISTANCE_APPROX(pAttacker->GetX()-ch->GetX(), pAttacker->GetY()-ch->GetY()) );
return;
}
int overlapDamageCount = 0;
int pct = 0;
if (ch->GetJob() == Set1)
{
const char* ptr = NULL;
switch ( Set1 )
{
case JOB_WARRIOR: ptr = "musa"; break;
case JOB_ASSASSIN: ptr = "assa"; break;
case JOB_SURA: ptr = "sura"; break;
case JOB_SHAMAN: ptr = "muda"; break;
default:
case JOB_MAX_NUM: return;
}
int firstDamagePercent = number(BlueDragon_GetSkillFactor(4, "Skill0", "damage", ptr, "min"), BlueDragon_GetSkillFactor(4, "Skill0", "damage", ptr, "max"));
pct += firstDamagePercent;
if (firstDamagePercent > 0)
overlapDamageCount++;
}
if (ch->GetJob() == Set2)
{
const char* ptr = NULL;
switch ( Set2 )
{
case JOB_WARRIOR: ptr = "musa"; break;
case JOB_ASSASSIN: ptr = "assa"; break;
case JOB_SURA: ptr = "sura"; break;
case JOB_SHAMAN: ptr = "muda"; break;
default:
case JOB_MAX_NUM: return;
}
int secondDamagePercent = number(BlueDragon_GetSkillFactor(4, "Skill0", "damage", ptr, "min"), BlueDragon_GetSkillFactor(4, "Skill0", "damage", ptr, "max"));
pct += secondDamagePercent;
if (secondDamagePercent > 0)
overlapDamageCount++;
}
if (GET_SEX(ch) == gender)
{
const char* ptr = NULL;
switch (gender)
{
case SEX_MALE: ptr = "male"; break;
case SEX_FEMALE: ptr = "female"; break;
default: return;
}
int thirdDamagePercent = number(BlueDragon_GetSkillFactor(4, "Skill0", "gender", ptr, "min"), BlueDragon_GetSkillFactor(4, "Skill0", "gender", ptr, "max"));
pct += thirdDamagePercent;
if (thirdDamagePercent > 0)
overlapDamageCount++;
}
switch (overlapDamageCount)
{
case 1:
ch->EffectPacket(SE_PERCENT_DAMAGE1);
break;
case 2:
ch->EffectPacket(SE_PERCENT_DAMAGE2);
break;
case 3:
ch->EffectPacket(SE_PERCENT_DAMAGE3);
break;
}
int addPct = BlueDragon_GetRangeFactor("hp_damage", pAttacker->GetHPPct());
pct += addPct;
int dam = number(BlueDragon_GetSkillFactor(3, "Skill0", "default_damage", "min"), BlueDragon_GetSkillFactor(3, "Skill0", "default_damage", "max"));
dam += (dam * addPct) / 100;
dam += (ch->GetMaxHP() * pct) / 100;
ch->Damage( pAttacker, dam, DAMAGE_TYPE_ICE );
sys_log(0, "BlueDragon: Breath to %s pct(%d) dam(%d) overlap(%d)", ch->GetName(), pct, dam, overlapDamageCount);
}
}
}
}
};
struct FSkillWeakBreath
{
LPCHARACTER pAttacker;
FSkillWeakBreath(LPCHARACTER p)
{
pAttacker = p;
}
void operator()(LPENTITY ent)
{
if (NULL != ent)
{
if (true == ent->IsType(ENTITY_CHARACTER))
{
LPCHARACTER ch = static_cast<LPCHARACTER>(ent);
if (true == ch->IsPC() && false == ch->IsDead())
{
if (NULL != ch->FindAffect(AFFECT_REVIVE_INVISIBLE, APPLY_NONE))
return;
if ((signed)BlueDragon_GetSkillFactor(2, "Skill1", "damage_area") < DISTANCE_APPROX(pAttacker->GetX()-ch->GetX(), pAttacker->GetY()-ch->GetY()))
{
sys_log(0, "BlueDragon: Breath too far (%d)", DISTANCE_APPROX(pAttacker->GetX()-ch->GetX(), pAttacker->GetY()-ch->GetY()) );
return;
}
int addPct = BlueDragon_GetRangeFactor("hp_damage", pAttacker->GetHPPct());
int dam = number( BlueDragon_GetSkillFactor(3, "Skill1", "default_damage", "min"), BlueDragon_GetSkillFactor(3, "Skill1", "default_damage", "max") );
dam += (dam * addPct) / 100;
ch->Damage( pAttacker, dam, DAMAGE_TYPE_ICE );
sys_log(0, "BlueDragon: WeakBreath to %s addPct(%d) dam(%d)", ch->GetName(), addPct, dam);
}
}
}
}
};
struct FSkillEarthQuake
{
EJobs Set1;
EJobs Set2;
ESex gender;
long MaxDistance;
LPCHARACTER pAttacker;
LPCHARACTER pFarthestChar;
FSkillEarthQuake(LPCHARACTER p)
{
pAttacker = p;
MaxDistance = 0;
pFarthestChar = NULL;
Set1 = static_cast<EJobs>(number(0,3));
Set2 = static_cast<EJobs>(number(0,3));
gender = static_cast<ESex>(number(0,2));
}
void operator()(LPENTITY ent)
{
if (NULL != ent)
{
if (true == ent->IsType(ENTITY_CHARACTER))
{
LPCHARACTER ch = static_cast<LPCHARACTER>(ent);
if (true == ch->IsPC() && false == ch->IsDead())
{
if (NULL != ch->FindAffect(AFFECT_REVIVE_INVISIBLE, APPLY_NONE))
return;
if ((signed)BlueDragon_GetSkillFactor(2, "Skill2", "damage_area") < DISTANCE_APPROX(pAttacker->GetX()-ch->GetX(), pAttacker->GetY()-ch->GetY()))
{
sys_log(0, "BlueDragon: Breath too far (%d)", DISTANCE_APPROX(pAttacker->GetX()-ch->GetX(), pAttacker->GetY()-ch->GetY()) );
return;
}
int sec = number(BlueDragon_GetSkillFactor(4, "Skill2", "stun_time", "default", "min"), BlueDragon_GetSkillFactor(4, "Skill2", "stun_time", "default", "max"));
if (ch->GetJob() == Set1)
{
const char* ptr = NULL;
switch ( Set1 )
{
case JOB_WARRIOR: ptr = "musa"; break;
case JOB_ASSASSIN: ptr = "assa"; break;
case JOB_SURA: ptr = "sura"; break;
case JOB_SHAMAN: ptr = "muda"; break;
default:
case JOB_MAX_NUM: return;
}
sec += number(BlueDragon_GetSkillFactor(4, "Skill2", "stun_time", ptr, "min"), BlueDragon_GetSkillFactor(4, "Skill2", "stun_time", ptr, "max"));
}
if (ch->GetJob() == Set2)
{
const char* ptr = NULL;
switch ( Set2 )
{
case JOB_WARRIOR: ptr = "musa"; break;
case JOB_ASSASSIN: ptr = "assa"; break;
case JOB_SURA: ptr = "sura"; break;
case JOB_SHAMAN: ptr = "muda"; break;
default:
case JOB_MAX_NUM: return;
}
sec += number(BlueDragon_GetSkillFactor(4, "Skill2", "stun_time", ptr, "min"), BlueDragon_GetSkillFactor(4, "Skill2", "stun_time", ptr, "max"));
}
if (GET_SEX(ch) == gender)
{
const char* ptr = NULL;
switch (gender)
{
case SEX_MALE: ptr = "male"; break;
case SEX_FEMALE: ptr = "female"; break;
default: return;
}
sec += number(BlueDragon_GetSkillFactor(4, "Skill2", "gender", ptr, "min"), BlueDragon_GetSkillFactor(4, "Skill2", "gender", ptr, "max"));
}
int addPct = BlueDragon_GetRangeFactor("hp_damage", pAttacker->GetHPPct());
int dam = number( BlueDragon_GetSkillFactor(3, "Skill2", "default_damage", "min"), BlueDragon_GetSkillFactor(3, "Skill2", "default_damage", "max") );
dam += (dam * addPct) / 100;
ch->Damage( pAttacker, dam, DAMAGE_TYPE_ICE);
SkillAttackAffect( ch, 1000, IMMUNE_STUN, AFFECT_STUN, POINT_NONE, 0, AFF_STUN, sec, "BDRAGON_STUN" );
sys_log(0, "BlueDragon: EarthQuake to %s addPct(%d) dam(%d) sec(%d)", ch->GetName(), addPct, dam, sec);
VECTOR vec;
vec.x = static_cast<float>(pAttacker->GetX() - ch->GetX());
vec.y = static_cast<float>(pAttacker->GetY() - ch->GetY());
vec.z = 0.0f;
Normalize( &vec, &vec );
const int nFlyDistance = 1000;
long tx = ch->GetX() + vec.x * nFlyDistance;
long ty = ch->GetY() + vec.y * nFlyDistance;
for (int i=0 ; i < 5 ; ++i)
{
if (true == SECTREE_MANAGER::instance().IsMovablePosition( ch->GetMapIndex(), tx, ty ))
{
break;
}
switch( i )
{
case 0:
tx = ch->GetX() + vec.x * nFlyDistance * -1;
ty = ch->GetY() + vec.y * nFlyDistance * -1;
break;
case 1:
tx = ch->GetX() + vec.x * nFlyDistance * -1;
ty = ch->GetY() + vec.y * nFlyDistance;
break;
case 2:
tx = ch->GetX() + vec.x * nFlyDistance;
ty = ch->GetY() + vec.y * nFlyDistance * -1;
break;
case 3:
tx = ch->GetX() + vec.x * number(1,100);
ty = ch->GetY() + vec.y * number(1,100);
break;
case 4:
tx = ch->GetX() + vec.x * number(1,10);
ty = ch->GetY() + vec.y * number(1,10);
break;
}
}
ch->Sync( tx , ty );
ch->Goto( tx , ty );
ch->CalculateMoveDuration();
ch->SyncPacket();
long dist = DISTANCE_APPROX( pAttacker->GetX() - ch->GetX(), pAttacker->GetY() - ch->GetY() );
if (dist > MaxDistance)
{
MaxDistance = dist;
pFarthestChar = ch;
}
}
}
}
}
};

View File

@ -0,0 +1,225 @@
#include "stdafx.h"
#include "ClientPackageCryptInfo.h"
#include "../../common/stl.h"
#ifndef __FreeBSD__
#include "../../libthecore/include/xdirent.h"
#endif
CClientPackageCryptInfo::CClientPackageCryptInfo() : m_pSerializedCryptKeyStream(NULL), m_nCryptKeyPackageCnt(0)
{
}
CClientPackageCryptInfo::~CClientPackageCryptInfo()
{
m_vecPackageCryptKeys.clear();
m_mapPackageSDB.clear();
if( m_pSerializedCryptKeyStream )
{
delete[] m_pSerializedCryptKeyStream;
m_pSerializedCryptKeyStream = NULL;
}
}
bool CClientPackageCryptInfo::LoadPackageCryptFile( const char* pCryptFile )
{
FILE * fp = fopen(pCryptFile, "rb");
if (!fp)
return false;
int iSDBDataOffset;
fread(&iSDBDataOffset, sizeof(int), 1, fp);
int iPackageCnt;
fread( &iPackageCnt, sizeof(int), 1, fp );
m_nCryptKeyPackageCnt += iPackageCnt;
int iCryptKeySize = iSDBDataOffset - 2*sizeof(int);
{
if (0 == iCryptKeySize)
{
sys_log(0, "[PackageCryptInfo] failed to load crypt key. (file: %s, key size: %d)", pCryptFile, iCryptKeySize);
m_nCryptKeyPackageCnt -= iPackageCnt;
}
else
{
int nCurKeySize = (int)m_vecPackageCryptKeys.size();
m_vecPackageCryptKeys.resize( nCurKeySize + sizeof(int) + iCryptKeySize);
memcpy( &m_vecPackageCryptKeys[nCurKeySize], &iCryptKeySize, sizeof(int));
fread( &m_vecPackageCryptKeys[nCurKeySize + sizeof(int)], sizeof(BYTE), iCryptKeySize, fp );
sys_log(0, "[PackageCryptInfo] %s loaded. (key size: %d, count: %d, total: %d)", pCryptFile, iCryptKeySize, iPackageCnt, m_nCryptKeyPackageCnt);
}
}
//about SDB data
//total packagecnt (4byte)
// for packagecnt
// db name hash 4byte( stl.h stringhash ) +child node size(4byte)
//stream to client
// sdb file cnt( 4byte )
// for sdb file cnt
// filename hash ( stl.h stringhash )
// related map name size(4), relate map name
// sdb block size( 1byte )
// sdb blocks
int iSDBPackageCnt;
fread(&iSDBPackageCnt, sizeof(int), 1, fp);
DWORD dwPackageNameHash, dwPackageStreamSize, dwSDBFileCnt, dwFileNameHash, dwMapNameSize;
std::string strRelatedMapName;
if (0 == iCryptKeySize && 0 == iSDBPackageCnt)
return false;
for( int i = 0; i < iSDBPackageCnt; ++i )
{
fread(&dwPackageNameHash, sizeof(DWORD), 1, fp);
fread(&dwPackageStreamSize, sizeof(DWORD), 1, fp);
fread(&dwSDBFileCnt, sizeof(DWORD), 1, fp);
sys_log(0, "[PackageCryptInfo] SDB Loaded. (Name Hash : %d, Stream Size: %d, File Count: %d)", dwPackageNameHash,dwPackageStreamSize, dwSDBFileCnt);
for( int j = 0; j < (int)dwSDBFileCnt; ++j )
{
fread(&dwFileNameHash, sizeof(DWORD), 1, fp);
fread(&dwMapNameSize, sizeof(DWORD), 1, fp);
strRelatedMapName.resize( dwMapNameSize );
fread(&strRelatedMapName[0], sizeof(BYTE), dwMapNameSize, fp);
sys_log(0, "[PackageCryptInfo] \t SDB each file info loaded.(MapName: %s, NameHash: %X)", strRelatedMapName.c_str(), dwFileNameHash);
BYTE bSDBStreamSize;
std::vector<BYTE> vecSDBStream;
fread(&bSDBStreamSize, sizeof(BYTE), 1, fp);
vecSDBStream.resize(bSDBStreamSize);
fread(&vecSDBStream[0], sizeof(BYTE), bSDBStreamSize, fp);
//reconstruct it
TPackageSDBMap::iterator it = m_mapPackageSDB.find( strRelatedMapName );
if( it == m_mapPackageSDB.end() )
{
TPerFileSDBInfo fileSDBInfo;
m_mapPackageSDB[strRelatedMapName] = fileSDBInfo;
}
TSupplementaryDataBlockInfo SDBInfo;
std::vector<TSupplementaryDataBlockInfo>& rSDBInfos = m_mapPackageSDB[strRelatedMapName].vecSDBInfos;
{
SDBInfo.dwPackageIdentifier = dwPackageNameHash;
SDBInfo.dwFileIdentifier = dwFileNameHash;
SDBInfo.vecSDBStream.resize( bSDBStreamSize );
memcpy(&SDBInfo.vecSDBStream[0], &vecSDBStream[0], bSDBStreamSize );
rSDBInfos.push_back( SDBInfo );
}
}
}
fclose(fp);
return true;
}
bool CClientPackageCryptInfo::LoadPackageCryptInfo( const char* pCryptInfoDir )
{
DIR * pDir = opendir(pCryptInfoDir);
if (!pDir)
return false;
m_nCryptKeyPackageCnt = 0;
if( m_pSerializedCryptKeyStream )
{
delete[] m_pSerializedCryptKeyStream;
m_pSerializedCryptKeyStream = NULL;
}
m_mapPackageSDB.clear();
m_vecPackageCryptKeys.clear();
const char szPrefixCryptInfoFile[] = "cshybridcrypt";
dirent * pDirEnt;
while ((pDirEnt = readdir(pDir)))
{
//if (strncmp( &(pDirEnt->d_name[0]), szPrefixCryptInfoFile, strlen(szPrefixCryptInfoFile)) )
if (std::string::npos == std::string(pDirEnt->d_name).find(szPrefixCryptInfoFile))
{
sys_log(0, "[PackageCryptInfo] %s is not crypt file. pass!", pDirEnt->d_name);
continue;
}
std::string strFullPathName = std::string(pCryptInfoDir) + std::string(pDirEnt->d_name);
sys_log(0, "[PackageCryptInfo] Try to load crypt file: %s", strFullPathName.c_str());
if (false == LoadPackageCryptFile( strFullPathName.c_str() ))
sys_err("[PackageCryptInfo] Failed to load %s", strFullPathName.c_str());
}
closedir(pDir);
return true;
}
void CClientPackageCryptInfo::GetPackageCryptKeys( BYTE** ppData, int& iDataSize )
{
int nCryptKeySize = m_vecPackageCryptKeys.size();
int iStreamSize = sizeof(int)+nCryptKeySize;
//NOTE : Crypt Key Info isn`t updated during runtime. ( in case of file reloading all data is cleared & recreated )
//it`s not safe but due to performance benefit we don`t do re-serialize.
if( m_pSerializedCryptKeyStream )
{
*ppData = m_pSerializedCryptKeyStream;
iDataSize = iStreamSize;
return;
}
if( nCryptKeySize > 0 )
{
m_pSerializedCryptKeyStream = new BYTE[iStreamSize];
memcpy(&m_pSerializedCryptKeyStream[0], &m_nCryptKeyPackageCnt, sizeof(int) );
memcpy(&m_pSerializedCryptKeyStream[sizeof(int)], &m_vecPackageCryptKeys[0], nCryptKeySize );
*ppData = m_pSerializedCryptKeyStream;
iDataSize = iStreamSize;
}
else
{
*ppData = NULL;
iDataSize = 0;
}
}
bool CClientPackageCryptInfo::GetRelatedMapSDBStreams(const char* pMapName, BYTE** ppData, int& iDataSize )
{
std::string strLowerMapName = pMapName;
stl_lowers(strLowerMapName);
TPackageSDBMap::iterator it = m_mapPackageSDB.find( strLowerMapName.c_str() );
if( it == m_mapPackageSDB.end() || it->second.vecSDBInfos.size() == 0 )
{
//sys_err("GetRelatedMapSDBStreams Failed(%s)", strLowerMapName.c_str());
return false;
}
*ppData = it->second.GetSerializedStream();
iDataSize = it->second.GetSize();
//sys_log(0, "GetRelatedMapSDBStreams Size(%d)", iDataSize);
return true;
}

View File

@ -0,0 +1,117 @@
#ifndef __INC_CLIENTPACKAGE_CRYPTINFO_H
#define __INC_CLIENTPACKAGE_CRYPTINFO_H
#include <boost/unordered_map.hpp>
#pragma pack(1)
typedef struct SSupplementaryDataBlockInfo
{
DWORD dwPackageIdentifier;
DWORD dwFileIdentifier;
std::vector<BYTE> vecSDBStream;
void Serialize( BYTE* pStream )
{
memcpy(pStream, &dwPackageIdentifier, sizeof(DWORD));
memcpy(pStream+4, &dwFileIdentifier, sizeof(DWORD));
BYTE bSize = vecSDBStream.size();
memcpy(pStream+8, &bSize, sizeof(BYTE));
memcpy(pStream+9, &vecSDBStream[0], bSize);
}
DWORD GetSerializedSize() const
{
return sizeof(DWORD)*2 + sizeof(BYTE) + vecSDBStream.size();
}
} TSupplementaryDataBlockInfo;
#pragma pack()
class CClientPackageCryptInfo
{
public:
CClientPackageCryptInfo();
~CClientPackageCryptInfo();
bool LoadPackageCryptInfo( const char* pCryptInfoDir );
void GetPackageCryptKeys( BYTE** ppData, int& iDataSize );
bool GetRelatedMapSDBStreams(const char* pMapName, BYTE** ppData, int& iDataSize );
private:
bool LoadPackageCryptFile( const char* pCryptFile );
private:
int m_nCryptKeyPackageCnt;
std::vector<BYTE> m_vecPackageCryptKeys;
BYTE* m_pSerializedCryptKeyStream;
typedef struct SPerFileSDBInfo
{
SPerFileSDBInfo() : m_pSerializedStream(NULL) {}
~SPerFileSDBInfo()
{
if(m_pSerializedStream)
{
delete[]m_pSerializedStream;
}
}
DWORD GetSize() const
{
DWORD dwSize = 4; //initial vecSDBInfo count
for(int i = 0; i < (int)vecSDBInfos.size(); ++i)
{
dwSize += vecSDBInfos[i].GetSerializedSize();
}
return dwSize;
}
BYTE* GetSerializedStream()
{
//NOTE : SDB Data isn`t updated during runtime. ( in case of file reloading all data is cleared & recreated )
//it`s not safe but due to performance benefit we don`t do re-serialize.
if(m_pSerializedStream)
return m_pSerializedStream;
m_pSerializedStream = new BYTE[GetSize()];
int iWrittenOffset = 0;
int iSDBInfoSize = vecSDBInfos.size();
//write size
memcpy( m_pSerializedStream, &iSDBInfoSize, sizeof(int) );
iWrittenOffset += sizeof(int);
for(int i = 0; i < iSDBInfoSize; ++i)
{
vecSDBInfos[i].Serialize( m_pSerializedStream + iWrittenOffset );
iWrittenOffset += vecSDBInfos[i].GetSerializedSize();
}
return m_pSerializedStream;
}
std::vector<TSupplementaryDataBlockInfo> vecSDBInfos;
private:
BYTE* m_pSerializedStream;
} TPerFileSDBInfo;
typedef boost::unordered_map<std::string, TPerFileSDBInfo > TPackageSDBMap; //key: related map name
TPackageSDBMap m_mapPackageSDB;
};
#endif //__INC_CLIENTPACKAGE_CRYPTINFO_H

255
game/src/DragonLair.cpp Normal file
View File

@ -0,0 +1,255 @@
#include "stdafx.h"
#include "DragonLair.h"
#include "entity.h"
#include "sectree_manager.h"
#include "char.h"
#include "guild.h"
#include "locale_service.h"
#include "regen.h"
#include "log.h"
#include "utils.h"
extern int passes_per_sec;
struct FWarpToDragronLairWithGuildMembers
{
DWORD dwGuildID;
long mapIndex;
long x, y;
FWarpToDragronLairWithGuildMembers( DWORD guildID, long map, long X, long Y )
: dwGuildID(guildID), mapIndex(map), x(X), y(Y)
{
}
void operator()(LPENTITY ent)
{
if (NULL != ent && true == ent->IsType(ENTITY_CHARACTER))
{
LPCHARACTER pChar = static_cast<LPCHARACTER>(ent);
if (true == pChar->IsPC())
{
if (NULL != pChar->GetGuild())
{
if (dwGuildID == pChar->GetGuild()->GetID())
{
pChar->WarpSet(x, y, mapIndex);
}
}
}
}
}
};
struct FWarpToVillage
{
void operator() (LPENTITY ent)
{
if (NULL != ent)
{
LPCHARACTER pChar = static_cast<LPCHARACTER>(ent);
if (NULL != pChar)
{
if (true == pChar->IsPC())
{
pChar->GoHome();
}
}
}
}
};
EVENTINFO(tag_DragonLair_Collapse_EventInfo)
{
int step;
CDragonLair* pLair;
long InstanceMapIndex;
tag_DragonLair_Collapse_EventInfo()
: step( 0 )
, pLair( 0 )
, InstanceMapIndex( 0 )
{
}
};
EVENTFUNC( DragonLair_Collapse_Event )
{
tag_DragonLair_Collapse_EventInfo* pInfo = dynamic_cast<tag_DragonLair_Collapse_EventInfo*>(event->info);
if ( pInfo == NULL )
{
sys_err( "DragonLair_Collapse_Event> <Factor> Null pointer" );
return 0;
}
if (0 == pInfo->step)
{
char buf[512];
snprintf(buf, 512, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> %d <20>ʸ<EFBFBD><CAB8><EFBFBD> <20>׾<EFBFBD><D7BE><EFBFBD>ȿ<EFBFBD>Ф<EFBFBD>"), pInfo->pLair->GetEstimatedTime());
SendNoticeMap(buf, pInfo->InstanceMapIndex, true);
pInfo->step++;
return PASSES_PER_SEC( 30 );
}
else if (1 == pInfo->step)
{
LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap( pInfo->InstanceMapIndex );
if (NULL != pMap)
{
FWarpToVillage f;
pMap->for_each( f );
}
pInfo->step++;
return PASSES_PER_SEC( 30 );
}
else
{
SECTREE_MANAGER::instance().DestroyPrivateMap( pInfo->InstanceMapIndex );
M2_DELETE(pInfo->pLair);
}
return 0;
}
CDragonLair::CDragonLair(DWORD guildID, long BaseMapID, long PrivateMapID)
: GuildID_(guildID), BaseMapIndex_(BaseMapID), PrivateMapIndex_(PrivateMapID)
{
StartTime_ = get_global_time();
}
CDragonLair::~CDragonLair()
{
}
DWORD CDragonLair::GetEstimatedTime() const
{
return get_global_time() - StartTime_;
}
void CDragonLair::OnDragonDead(LPCHARACTER pDragon)
{
sys_log(0, "DragonLair: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>׾<EFBFBD><D7BE><EFBFBD>ȿ");
LogManager::instance().DragonSlayLog( GuildID_, pDragon->GetMobTable().dwVnum, StartTime_, get_global_time() );
}
CDragonLairManager::CDragonLairManager()
{
}
CDragonLairManager::~CDragonLairManager()
{
}
bool CDragonLairManager::Start(long MapIndexFrom, long BaseMapIndex, DWORD GuildID)
{
long instanceMapIndex = SECTREE_MANAGER::instance().CreatePrivateMap(BaseMapIndex);
if (instanceMapIndex == 0) {
sys_err("CDragonLairManager::Start() : no private map index available");
return false;
}
LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(MapIndexFrom);
if (NULL != pMap)
{
LPSECTREE_MAP pTargetMap = SECTREE_MANAGER::instance().GetMap(BaseMapIndex);
if (NULL == pTargetMap)
{
return false;
}
const TMapRegion* pRegionInfo = SECTREE_MANAGER::instance().GetMapRegion( pTargetMap->m_setting.iIndex );
if (NULL != pRegionInfo)
{
FWarpToDragronLairWithGuildMembers f(GuildID, instanceMapIndex, 844000, 1066900);
pMap->for_each( f );
LairMap_.insert( std::make_pair(GuildID, M2_NEW CDragonLair(GuildID, BaseMapIndex, instanceMapIndex)) );
std::string strMapBasePath( LocaleService_GetMapPath() );
strMapBasePath += "/" + pRegionInfo->strMapName + "/instance_regen.txt";
sys_log(0, "%s", strMapBasePath.c_str());
regen_do(strMapBasePath.c_str(), instanceMapIndex, pTargetMap->m_setting.iBaseX, pTargetMap->m_setting.iBaseY, NULL, true);
return true;
}
}
return false;
}
void CDragonLairManager::OnDragonDead(LPCHARACTER pDragon, DWORD KillerGuildID)
{
if (NULL == pDragon)
return;
if (false == pDragon->IsMonster())
return;
boost::unordered_map<DWORD, CDragonLair*>::iterator iter = LairMap_.find( KillerGuildID );
if (LairMap_.end() == iter)
{
return;
}
LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap( pDragon->GetMapIndex() );
if (NULL == iter->second || NULL == pMap)
{
LairMap_.erase( iter );
return;
}
iter->second->OnDragonDead( pDragon );
// <20>ֵ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD>ֱ<EFBFBD>
tag_DragonLair_Collapse_EventInfo* info;
info = AllocEventInfo<tag_DragonLair_Collapse_EventInfo>();
info->step = 0;
info->pLair = iter->second;
info->InstanceMapIndex = pDragon->GetMapIndex();
event_create(DragonLair_Collapse_Event, info, PASSES_PER_SEC(10));
LairMap_.erase( iter );
}

37
game/src/DragonLair.h Normal file
View File

@ -0,0 +1,37 @@
#include <boost/unordered_map.hpp>
#include "../../common/stl.h"
class CDragonLair
{
public:
CDragonLair (DWORD dwGuildID, long BaseMapID, long PrivateMapID);
virtual ~CDragonLair ();
DWORD GetEstimatedTime () const;
void OnDragonDead (LPCHARACTER pDragon);
private:
DWORD StartTime_;
DWORD GuildID_;
long BaseMapIndex_;
long PrivateMapIndex_;
};
class CDragonLairManager : public singleton<CDragonLairManager>
{
public:
CDragonLairManager ();
virtual ~CDragonLairManager ();
bool Start (long MapIndexFrom, long BaseMapIndex, DWORD GuildID);
void OnDragonDead (LPCHARACTER pDragon, DWORD KillerGuildID);
size_t GetLairCount () const { return LairMap_.size(); }
private:
boost::unordered_map<DWORD, CDragonLair*> LairMap_;
};

1151
game/src/DragonSoul.cpp Normal file

File diff suppressed because it is too large Load Diff

60
game/src/DragonSoul.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef __INC_METIN_II_GAME_DRAGON_SOUL_H__
#define __INC_METIN_II_GAME_DRAGON_SOUL_H__
#include "../../common/length.h"
class CHARACTER;
class CItem;
class DragonSoulTable;
class DSManager : public singleton<DSManager>
{
public:
DSManager();
~DSManager();
bool ReadDragonSoulTableFile(const char * c_pszFileName);
void GetDragonSoulInfo(DWORD dwVnum, OUT BYTE& bType, OUT BYTE& bGrade, OUT BYTE& bStep, OUT BYTE& bRefine) const;
// fixme : titempos<6F><73>
WORD GetBasePosition(const LPITEM pItem) const;
bool IsValidCellForThisItem(const LPITEM pItem, const TItemPos& Cell) const;
int GetDuration(const LPITEM pItem) const;
// <20><>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD> <20>޾Ƽ<DEBE> Ư<><C6AF> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>Լ<EFBFBD>
bool ExtractDragonHeart(LPCHARACTER ch, LPITEM pItem, LPITEM pExtractor = NULL);
// Ư<><C6AF> <20><>ȥ<EFBFBD><C8A5>(pItem)<29><> <20><><EFBFBD><EFBFBD>â<EFBFBD><C3A2><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>θ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD>,
// <20><><EFBFBD>н<EFBFBD> <20>λ깰<CEBB><EAB9B0> <20>ִ<EFBFBD> <20>Լ<EFBFBD>.(<28>λ깰<CEBB><EAB9B0> dragon_soul_table.txt<78><74> <20><><EFBFBD><EFBFBD>)
// DestCell<6C><6C> invalid<69><64> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>, <20><>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ڵ<EFBFBD> <20>߰<EFBFBD>.
// <20><><EFBFBD><EFBFBD> <20><>, <20><>ȥ<EFBFBD><C8A5>(pItem)<29><> delete<74><65>.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִٸ<D6B4> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Ȯ<><C8AE><EFBFBD><EFBFBD> pExtractor->GetValue(0)%<25><>ŭ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
// <20>λ깰<CEBB><EAB9B0> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ڵ<EFBFBD> <20>߰<EFBFBD>.
bool PullOut(LPCHARACTER ch, TItemPos DestCell, IN OUT LPITEM& pItem, LPITEM pExtractor = NULL);
// <20><>ȥ<EFBFBD><C8A5> <20><><EFBFBD>׷<EFBFBD><D7B7>̵<EFBFBD> <20>Լ<EFBFBD>
bool DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_REFINE_GRID_SIZE]);
bool DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_REFINE_GRID_SIZE]);
bool DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_REFINE_GRID_SIZE]);
bool DragonSoulItemInitialize(LPITEM pItem);
bool IsTimeLeftDragonSoul(LPITEM pItem) const;
int LeftTime(LPITEM pItem) const;
bool ActivateDragonSoul(LPITEM pItem);
bool DeactivateDragonSoul(LPITEM pItem, bool bSkipRefreshOwnerActiveState = false);
bool IsActiveDragonSoul(LPITEM pItem) const;
private:
void SendRefineResultPacket(LPCHARACTER ch, BYTE bSubHeader, const TItemPos& pos);
// ij<><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȥ<EFBFBD><C8A5> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><ECBAB8>, Ȱ<><C8B0>ȭ <20><> <20><>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD> <20><><EFBFBD>ٸ<EFBFBD>, ij<><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȥ<EFBFBD><C8A5> Ȱ<><C8B0> <20><><EFBFBD>¸<EFBFBD> off <20><>Ű<EFBFBD><C5B0> <20>Լ<EFBFBD>.
void RefreshDragonSoulState(LPCHARACTER ch);
DWORD MakeDragonSoulVnum(BYTE bType, BYTE grade, BYTE step, BYTE refine);
bool PutAttributes(LPITEM pDS);
bool RefreshItemAttributes(LPITEM pItem);
DragonSoulTable* m_pTable;
};
#endif

64
game/src/FSM.cpp Normal file
View File

@ -0,0 +1,64 @@
// Local Includes
#include <cassert>
#include <cstdlib>
#include "FSM.h"
// Constructor
CFSM::CFSM()
{
// Initialize States
m_stateInitial.Set(this, &CFSM::BeginStateInitial, &CFSM::StateInitial, &CFSM::EndStateInitial);
// Initialize State Machine
m_pCurrentState = static_cast<CState *>(&m_stateInitial);
m_pNewState = NULL;
}
//======================================================================================================
// Global Functions
// Update
void CFSM::Update()
{
// Check New State
if (m_pNewState)
{
if (NULL != m_pCurrentState)
{
m_pCurrentState->ExecuteEndState();
}
// Set New State
m_pCurrentState = m_pNewState;
m_pNewState = 0;
// Execute Begin State
m_pCurrentState->ExecuteBeginState();
}
// Execute State
m_pCurrentState->ExecuteState();
}
//======================================================================================================
// State Functions
// Is State
bool CFSM::IsState(CState & State) const
{
return (m_pCurrentState == &State);
}
// Goto State
bool CFSM::GotoState(CState & NewState)
{
if (IsState(NewState) && m_pNewState == &NewState)
return true;
// Set New State
m_pNewState = &NewState;
return true;
}

34
game/src/FSM.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef _fsm_fsm_h
#define _fsm_fsm_h
// Local Includes
#include "state.h"
// FSM Class
class CFSM
{
protected:
CState * m_pCurrentState; // Current State
CState * m_pNewState; // New State
CStateTemplate<CFSM> m_stateInitial; // Initial State
public:
// Constructor
CFSM();
// Destructor
virtual ~CFSM() {}
// Global Functions
virtual void Update();
// State Functions
bool IsState(CState &State) const;
bool GotoState(CState &NewState);
virtual void BeginStateInitial() {}
virtual void StateInitial() {}
virtual void EndStateInitial() {}
};
#endif

View File

@ -0,0 +1,136 @@
#include "stdafx.h"
#include "FileMonitor_FreeBSD.h"
#include "../../libthecore/include/log.h"
#define INVALID_KERNEL_EVENT -1
FileMonitorFreeBSD::FileMonitorFreeBSD()
{
m_KernelEventQueue = INVALID_KERNEL_EVENT;
}
FileMonitorFreeBSD::~FileMonitorFreeBSD()
{
if( m_KernelEventQueue != INVALID_KERNEL_EVENT )
{
close ( m_KernelEventQueue );
m_KernelEventQueue = INVALID_KERNEL_EVENT;
}
TMonitorFileHashMap::iterator it;
for( it = m_FileLists.begin(); it != m_FileLists.end(); ++it )
{
close(it->second.fhMonitor);
}
m_FileLists.clear();
m_MonitoredEventLists.clear();
m_TriggeredEventLists.clear();
}
void FileMonitorFreeBSD::Update(DWORD dwPulses)
{
if( m_KernelEventQueue == INVALID_KERNEL_EVENT || m_FileLists.size() == 0 )
return;
int nEvent = kevent(m_KernelEventQueue, &m_TriggeredEventLists[0], (int)m_TriggeredEventLists.size(), &m_MonitoredEventLists[0], (int)m_MonitoredEventLists.size(), NULL );
if( nEvent == INVALID_KERNEL_EVENT )
{
return;
}
else if( nEvent > 0 )
{
for( int i = 0; i < nEvent; ++i )
{
int nEventFlags = m_MonitoredEventLists[i].flags;
eFileUpdatedOptions eUpdateOption = e_FileUpdate_None;
if (nEventFlags & EV_ERROR)
eUpdateOption = e_FileUpdate_Error;
else if (nEventFlags & NOTE_DELETE)
eUpdateOption = e_FileUpdate_Deleted;
else if (nEventFlags & NOTE_EXTEND || nEventFlags & NOTE_WRITE)
eUpdateOption = e_FileUpdate_Modified;
else if (nEventFlags & NOTE_ATTRIB)
eUpdateOption = e_FileUpdate_AttrModified;
else if (nEventFlags & NOTE_LINK)
eUpdateOption = e_FileUpdate_Linked;
else if (nEventFlags & NOTE_RENAME)
eUpdateOption = e_FileUpdate_Renamed;
else if (nEventFlags & NOTE_REVOKE)
eUpdateOption = e_FileUpdate_Revoked;
if( eUpdateOption != e_FileUpdate_None )
{
TMonitorFileHashMap::iterator it;
for( it = m_FileLists.begin(); it != m_FileLists.end(); ++it )
{
FileIOContext_FreeBSD& context = it->second;
if( context.idxToEventList == i )
{
std::string strModifedFileName = it->first;
context.pListenFunc( strModifedFileName, eUpdateOption );
break;
}
}
}
}
}
}
void FileMonitorFreeBSD::AddWatch(const std::string& strFileName, PFN_FileChangeListener pListenerFunc)
{
int iFileHandle = -1;
if( (iFileHandle = open(strFileName.c_str(), O_RDONLY)) == -1)
{
sys_err("FileMonitorFreeBSD:AddWatch : can`t open file(%s).\n", strFileName.c_str());
return;
}
//create kqueue if not exists
if( m_KernelEventQueue == INVALID_KERNEL_EVENT )
m_KernelEventQueue = kqueue();
if( m_KernelEventQueue == INVALID_KERNEL_EVENT )
{
sys_err("FileMonitorFreeBSD:AddWatch : failed to create kqueue.\n");
return;
}
TMonitorFileHashMap::iterator it = m_FileLists.find( strFileName );
if( it != m_FileLists.end() )
{
sys_log(0, "FileMonitorFreeBSD:AddWatch : trying to add duplicated watch on file(%s).\n", strFileName.c_str() );
return;
}
//set file context
FileIOContext_FreeBSD context;
{
context.fhMonitor = iFileHandle;
context.idxToEventList = (int)m_MonitoredEventLists.size();
context.pListenFunc = pListenerFunc;
}
m_FileLists[strFileName] = context;
//set events
struct kevent kTriggerEvent, kMonitorEvent;
EV_SET(&kTriggerEvent, iFileHandle, EVFILT_VNODE,
EV_ADD | EV_ENABLE | EV_ONESHOT,
NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_LINK | NOTE_RENAME | NOTE_REVOKE,
0, 0);
m_TriggeredEventLists.push_back( kTriggerEvent );
m_MonitoredEventLists.push_back( kMonitorEvent );
}

View File

@ -0,0 +1,47 @@
#ifndef FILEMONITOR_FREEBSD_INCLUDED
#define FILEMONITOR_FREEBSD_INCLUDED
#include "IFileMonitor.h"
#include <unistd.h>
#include <sys/event.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/time.h>
struct FileIOContext_FreeBSD
{
int fhMonitor;
int idxToEventList; // evtTrigger & evtMonitor index should be same
PFN_FileChangeListener pListenFunc;
};
class FileMonitorFreeBSD : public IFileMonitor
{
private:
FileMonitorFreeBSD(); //hidden
public:
virtual ~FileMonitorFreeBSD();
void AddWatch (const std::string& strFileName, PFN_FileChangeListener pListenerFunc);
void Update (DWORD dwPulses);
static FileMonitorFreeBSD& Instance()
{
static FileMonitorFreeBSD theMonitor;
return theMonitor;
}
private:
typedef boost::unordered_map<std::string, FileIOContext_FreeBSD> TMonitorFileHashMap;
typedef std::vector<struct kevent> TEventList;
TMonitorFileHashMap m_FileLists;
TEventList m_MonitoredEventLists;
TEventList m_TriggeredEventLists;
int m_KernelEventQueue;
};
#endif //FILEMONITOR_FREEBSD_INCLUDED

54
game/src/HackShield.cpp Normal file
View File

@ -0,0 +1,54 @@
#include "stdafx.h"
#include "HackShield.h"
#include "HackShield_Impl.h"
#include "config.h"
bool CHackShieldManager::Initialize()
{
impl_ = M2_NEW CHackShieldImpl;
if (NULL == impl_)
{
return false;
}
return impl_->Initialize();
}
void CHackShieldManager::Release()
{
if (NULL != impl_)
{
impl_->Release();
M2_DELETE(impl_);
impl_ = NULL;
}
}
bool CHackShieldManager::CreateClientHandle(DWORD dwPlayerID)
{
return impl_->CreateClientHandle(dwPlayerID);
}
void CHackShieldManager::DeleteClientHandle(DWORD dwPlayerID)
{
impl_->DeleteClientHandle(dwPlayerID);
}
bool CHackShieldManager::SendCheckPacket(LPCHARACTER ch)
{
return impl_->SendCheckPacket(ch);
}
bool CHackShieldManager::VerifyAck(LPCHARACTER ch, const void* buf)
{
TPacketGCHSCheck* p = reinterpret_cast<TPacketGCHSCheck*>(const_cast<void*>(buf));
return impl_->VerifyAck(ch, p);
}

24
game/src/HackShield.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef HACK_SHIELD_MANAGER_H_
#define HACK_SHIELD_MANAGER_H_
class CHackShieldImpl;
class CHackShieldManager : public singleton<CHackShieldManager>
{
public:
bool Initialize ();
void Release ();
bool CreateClientHandle (DWORD dwPlayerID);
void DeleteClientHandle (DWORD dwPlayerID);
bool SendCheckPacket (LPCHARACTER ch);
bool VerifyAck (LPCHARACTER ch, const void* buf);
private:
CHackShieldImpl* impl_;
};
#endif /* HACK_SHIELD_MANAGER_H_ */

View File

@ -0,0 +1,202 @@
#include "stdafx.h"
#include "HackShield_Impl.h"
#ifdef __FreeBSD__
#include "char.h"
#include "packet.h"
#include "desc.h"
#include "log.h"
bool CHackShieldImpl::Initialize()
{
handle_ = _AhnHS_CreateServerObject("metin2client.bin.hsb");
if (ANTICPX_INVALID_HANDLE_VALUE == handle_)
{
return false;
}
sys_log(0, "HShield: Success to CreateServerObject");
return true;
}
void CHackShieldImpl::Release()
{
_AhnHS_CloseServerHandle(handle_);
sys_log(0, "HShield: Server Handle Closed");
}
bool CHackShieldImpl::CreateClientHandle(DWORD dwPlayerID)
{
ClientHandleContainer::const_iterator iter = CliehtHandleMap_.find( dwPlayerID );
if (iter != CliehtHandleMap_.end())
{
sys_log(0, "HShield: Client Handle is already created for Player(%u)", dwPlayerID);
return false;
}
AHNHS_CLIENT_HANDLE handle = _AhnHS_CreateClientObject(handle_);
if (ANTICPX_INVALID_HANDLE_VALUE == handle)
{
sys_log(0, "HShield: Failed to create client handle for Player(%u)", dwPlayerID);
return false;
}
CliehtHandleMap_.insert( std::make_pair(dwPlayerID, handle) );
sys_log(0, "HShield: Success to create client handle for Player(%u)", dwPlayerID);
return true;
}
void CHackShieldImpl::DeleteClientHandle(DWORD dwPlayerID)
{
ClientHandleContainer::iterator iter = CliehtHandleMap_.find( dwPlayerID );
if (iter == CliehtHandleMap_.end())
{
sys_log(0, "HShield: there is no client handle for Player(%u)", dwPlayerID);
return;
}
_AhnHS_CloseClientHandle(iter->second);
CliehtHandleMap_.erase(iter);
sys_log(0, "HShield: client handle deleted for Player(%u)", dwPlayerID);
}
bool CHackShieldImpl::SendCheckPacket(LPCHARACTER ch)
{
if (NULL == ch)
{
return false;
}
ClientHandleContainer::const_iterator iter = CliehtHandleMap_.find( ch->GetPlayerID() );
if (iter == CliehtHandleMap_.end())
{
sys_log(0, "HShield: Client Handle not create for Player(%u)", ch->GetPlayerID());
return false;
}
TPacketGCHSCheck pack;
pack.bHeader = HEADER_GC_HS_REQUEST;
memset( &pack.Req, 0, sizeof(pack.Req));
unsigned long ret = _AhnHS_MakeRequest( iter->second, &(pack.Req) );
if (0 != ret)
{
sys_log(0, "HShield: _AhnHS_MakeRequest return error(%u) for Player(%u)", ret, ch->GetPlayerID());
return false;
}
else
{
sys_log(0, "HShield: _AhnHS_MakeRequest success ret(%d)", ret);
}
if (NULL != ch->GetDesc())
{
ch->GetDesc()->Packet( &pack, sizeof(pack) );
sys_log(0, "HShield: Send Check Request for Player(%u)", ch->GetPlayerID());
return true;
}
sys_log(0, "HShield: Failed to get DESC for Player(%u)", ch->GetPlayerID());
return false;
}
bool CHackShieldImpl::VerifyAck(LPCHARACTER ch, TPacketGCHSCheck* buf)
{
if (NULL == ch)
{
return false;
}
bool NeedDisconnect = false;
ClientHandleContainer::const_iterator iter = CliehtHandleMap_.find( ch->GetPlayerID() );
if (iter == CliehtHandleMap_.end())
{
sys_log(0, "HShield: Cannot Find ClientHandle For Verify");
NeedDisconnect = true;
}
unsigned long dwError = 0;
unsigned long ret = _AhnHS_VerifyResponseEx( iter->second, buf->Req.byBuffer, buf->Req.nLength, &dwError );
if (ANTICPX_RECOMMAND_CLOSE_SESSION == ret)
{
sys_log(0, "HShield: not a valid ack ret(%u) error(%u) from Player(%u)", ret, dwError, ch->GetPlayerID());
NeedDisconnect = true;
ch->StopHackShieldCheckCycle();
}
if (NULL != ch->GetDesc())
{
if (true == NeedDisconnect)
{
ch->GetDesc()->SetPhase(PHASE_CLOSE);
LogManager::instance().HackShieldLog(dwError, ch);
return false;
}
else
{
ch->SetHackShieldCheckMode(false);
}
}
sys_log(0, "HShield: Valid Ack from Player(%u)", ch->GetPlayerID());
return true;
}
#else
bool CHackShieldImpl::Initialize()
{
return true;
}
void CHackShieldImpl::Release()
{
}
bool CHackShieldImpl::CreateClientHandle(DWORD dwPlayerID)
{
return true;
}
void CHackShieldImpl::DeleteClientHandle(DWORD dwPlayerID)
{
}
bool CHackShieldImpl::SendCheckPacket(LPCHARACTER ch)
{
return true;
}
bool CHackShieldImpl::VerifyAck(LPCHARACTER ch, TPacketGCHSCheck* buf)
{
return true;
}
#endif

View File

@ -0,0 +1,51 @@
#ifndef HACK_SHIELD_IMPL_H_
#define HACK_SHIELD_IMPL_H_
#include <boost/unordered_map.hpp>
#ifdef __FreeBSD__
// Live build only
#define UNIX
#include <AntiCpXSvr.h>
#undef UNIX
#endif
#pragma pack(1)
typedef struct SPacketGCHSCheck
{
BYTE bHeader;
#ifdef __FreeBSD__
AHNHS_TRANS_BUFFER Req;
#endif
} TPacketGCHSCheck;
#pragma pack()
class CHackShieldImpl
{
public:
bool Initialize ();
void Release ();
bool CreateClientHandle (DWORD dwPlayerID);
void DeleteClientHandle (DWORD dwPlayerID);
bool SendCheckPacket (LPCHARACTER ch);
bool VerifyAck (LPCHARACTER ch, TPacketGCHSCheck* buf);
private:
#ifdef __FreeBSD__
AHNHS_SERVER_HANDLE handle_;
typedef boost::unordered_map<DWORD, AHNHS_CLIENT_HANDLE> ClientHandleContainer;
ClientHandleContainer CliehtHandleMap_;
typedef boost::unordered_map<DWORD, bool> ClientCheckContainer;
ClientCheckContainer ClientCheckMap_;
#endif
};
#endif /* HACK_SHIELD_IMPL_H_ */

30
game/src/IFileMonitor.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef IFILEMONITOR_INCLUDED
#define IFILEMONITOR_INCLUDED
//#include <boost/function.hpp>
#include <boost/unordered_map.hpp>
enum eFileUpdatedOptions
{
e_FileUpdate_None = -1,
e_FileUpdate_Error,
e_FileUpdate_Deleted,
e_FileUpdate_Modified,
e_FileUpdate_AttrModified,
e_FileUpdate_Linked,
e_FileUpdate_Renamed,
e_FileUpdate_Revoked,
};
// TODO : in FreeBSD boost function doesn`t work with boost bind
// so currently we only support for static function ptr only
//typedef boost::function< void ( const std::string&, eFileUpdatedOptions ) > PFN_FileChangeListener;
typedef void (* PFN_FileChangeListener )(const std::string&, eFileUpdatedOptions);
struct IFileMonitor
{
virtual void Update (DWORD dwPulses) = 0;
virtual void AddWatch (const std::string& strFileName, PFN_FileChangeListener pListenerFunc) = 0;
};
#endif // IFILEMONITOR_INCLUDED

135
game/src/MarkConvert.cpp Normal file
View File

@ -0,0 +1,135 @@
#include "stdafx.h"
#include "MarkManager.h"
#ifdef __WIN32__
#include <direct.h>
#endif
#define OLD_MARK_INDEX_FILENAME "guild_mark.idx"
#define OLD_MARK_DATA_FILENAME "guild_mark.tga"
static Pixel * LoadOldGuildMarkImageFile()
{
FILE * fp = fopen(OLD_MARK_DATA_FILENAME, "rb");
if (!fp)
{
sys_err("cannot open %s", OLD_MARK_INDEX_FILENAME);
return NULL;
}
int dataSize = 512 * 512 * sizeof(Pixel);
Pixel * dataPtr = (Pixel *) malloc(dataSize);
fread(dataPtr, dataSize, 1, fp);
fclose(fp);
return dataPtr;
}
bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
{
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
#ifndef __WIN32__
mkdir("mark", S_IRWXU);
#else
_mkdir("mark");
#endif
// <20>ε<EFBFBD><CEB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֳ<EFBFBD>?
#ifndef __WIN32__
if (0 != access(OLD_MARK_INDEX_FILENAME, F_OK))
#else
if (0 != _access(OLD_MARK_INDEX_FILENAME, 0))
#endif
return true;
// <20>ε<EFBFBD><CEB5><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
FILE* fp = fopen(OLD_MARK_INDEX_FILENAME, "r");
if (NULL == fp)
return false;
// <20>̹<EFBFBD><CCB9><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
Pixel * oldImagePtr = LoadOldGuildMarkImageFile();
if (NULL == oldImagePtr)
{
fclose(fp);
return false;
}
/*
// guild_mark.tga<67><61> <20><><EFBFBD><EFBFBD> targa <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ƴϰ<C6B4>, 512 * 512 * 4 ũ<><C5A9><EFBFBD><EFBFBD> raw <20><><EFBFBD><EFBFBD><EFBFBD>̴<EFBFBD>.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ȯ<><C8AE><EFBFBD>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> targa <20><><EFBFBD>Ϸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
CGuildMarkImage * pkImage = new CGuildMarkImage;
pkImage->Build("guild_mark_real.tga");
pkImage->Load("guild_mark_real.tga");
pkImage->PutData(0, 0, 512, 512, oldImagePtr);
pkImage->Save("guild_mark_real.tga");
*/
sys_log(0, "Guild Mark Converting Start.");
char line[256];
DWORD guild_id;
DWORD mark_id;
Pixel mark[SGuildMark::SIZE];
while (fgets(line, sizeof(line)-1, fp))
{
sscanf(line, "%u %u", &guild_id, &mark_id);
if (find(vecGuildID.begin(), vecGuildID.end(), guild_id) == vecGuildID.end())
{
sys_log(0, " skipping guild ID %u", guild_id);
continue;
}
// mark id -> <20>̹<EFBFBD><CCB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ġ ã<><C3A3>
uint row = mark_id / 32;
uint col = mark_id % 32;
if (row >= 42)
{
sys_err("invalid mark_id %u", mark_id);
continue;
}
uint sx = col * 16;
uint sy = row * 12;
Pixel * src = oldImagePtr + sy * 512 + sx;
Pixel * dst = mark;
// <20><><EFBFBD><EFBFBD> <20>̹<EFBFBD><CCB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ũ <20>Ѱ<EFBFBD> <20><><EFBFBD><EFBFBD>
for (int y = 0; y != SGuildMark::HEIGHT; ++y)
{
for (int x = 0; x != SGuildMark::WIDTH; ++x)
*(dst++) = *(src+x);
src += 512;
}
// <20><> <20><><EFBFBD><EFBFBD> <20><>ũ <20>ý<EFBFBD><C3BD>ۿ<EFBFBD> <20>ִ´<D6B4>.
CGuildMarkManager::instance().SaveMark(guild_id, (BYTE *) mark);
line[0] = '\0';
}
free(oldImagePtr);
fclose(fp);
// <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20>ѹ<EFBFBD><D1B9><EFBFBD> <20>ϸ<EFBFBD><CFB8>ǹǷ<C7B9> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ű<EFBFBD><C5B0>ش<EFBFBD>.
#ifndef __WIN32__
system("mv -f guild_mark.idx guild_mark.idx.removable");
system("mv -f guild_mark.tga guild_mark.tga.removable");
#else
system("move /Y guild_mark.idx guild_mark.idx.removable");
system("move /Y guild_mark.tga guild_mark.tga.removable");
#endif
sys_log(0, "Guild Mark Converting Complete.");
return true;
}

299
game/src/MarkImage.cpp Normal file
View File

@ -0,0 +1,299 @@
#include "stdafx.h"
#include "MarkImage.h"
#include "crc32.h"
#include "lzo_manager.h"
#define CLZO LZOManager
CGuildMarkImage * NewMarkImage()
{
return M2_NEW CGuildMarkImage;
}
void DeleteMarkImage(CGuildMarkImage * pkImage)
{
M2_DELETE(pkImage);
}
CGuildMarkImage::CGuildMarkImage()
: m_uImg(INVALID_HANDLE)
{
memset( &m_apxImage, 0, sizeof(m_apxImage) );
}
CGuildMarkImage::~CGuildMarkImage()
{
Destroy();
}
void CGuildMarkImage::Destroy()
{
if (INVALID_HANDLE == m_uImg)
return;
ilDeleteImages(1, &m_uImg);
m_uImg = INVALID_HANDLE;
}
void CGuildMarkImage::Create()
{
if (INVALID_HANDLE != m_uImg)
return;
ilGenImages(1, &m_uImg);
}
bool CGuildMarkImage::Save(const char* c_szFileName)
{
ilEnable(IL_FILE_OVERWRITE);
ilBindImage(m_uImg);
if (!ilSave(IL_TGA, (const ILstring)c_szFileName))
return false;
return true;
}
bool CGuildMarkImage::Build(const char * c_szFileName)
{
sys_log(0, "GuildMarkImage: creating new file %s", c_szFileName);
Destroy();
Create();
ilBindImage(m_uImg);
ilEnable(IL_ORIGIN_SET);
ilOriginFunc(IL_ORIGIN_UPPER_LEFT);
BYTE * data = (BYTE *) malloc(sizeof(Pixel) * WIDTH * HEIGHT);
memset(data, 0, sizeof(Pixel) * WIDTH * HEIGHT);
if (!ilTexImage(WIDTH, HEIGHT, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, data))
{
sys_err("GuildMarkImage: cannot initialize image");
return false;
}
free(data);
ilEnable(IL_FILE_OVERWRITE);
if (!ilSave(IL_TGA, (const ILstring)c_szFileName))
return false;
return true;
}
bool CGuildMarkImage::Load(const char * c_szFileName)
{
Destroy();
Create();
ilBindImage(m_uImg);
ilEnable(IL_ORIGIN_SET);
ilOriginFunc(IL_ORIGIN_UPPER_LEFT);
if (!ilLoad(IL_TYPE_UNKNOWN, (const ILstring) c_szFileName))
{
sys_err("GuildMarkImage: %s cannot open file.", c_szFileName);
return false;
}
if (ilGetInteger(IL_IMAGE_WIDTH) != WIDTH)
{
sys_err("GuildMarkImage: %s width must be %u", c_szFileName, WIDTH);
return false;
}
if (ilGetInteger(IL_IMAGE_HEIGHT) != HEIGHT)
{
sys_err("GuildMarkImage: %s height must be %u", c_szFileName, HEIGHT);
return false;
}
ilConvertImage(IL_BGRA, IL_UNSIGNED_BYTE);
BuildAllBlocks();
return true;
}
void CGuildMarkImage::PutData(UINT x, UINT y, UINT width, UINT height, void * data)
{
ilBindImage(m_uImg);
ilSetPixels(x, y, 0, width, height, 1, IL_BGRA, IL_UNSIGNED_BYTE, data);
}
void CGuildMarkImage::GetData(UINT x, UINT y, UINT width, UINT height, void * data)
{
ilBindImage(m_uImg);
ilCopyPixels(x, y, 0, width, height, 1, IL_BGRA, IL_UNSIGNED_BYTE, data);
}
// <20>̹<EFBFBD><CCB9><EFBFBD> = 512x512
// <20><><EFBFBD><EFBFBD> = <20><>ũ 4 x 4
// <20><>ũ = 16 x 12
// <20><> <20>̹<EFBFBD><CCB9><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> = 8 x 10
// SERVER
bool CGuildMarkImage::SaveMark(DWORD posMark, BYTE * pbImage)
{
if (posMark >= MARK_TOTAL_COUNT)
{
sys_err("GuildMarkImage::CopyMarkFromData: Invalid mark position %u", posMark);
return false;
}
// <20><>ũ<EFBFBD><C5A9> <20><>ü <20>̹<EFBFBD><CCB9><EFBFBD><EFBFBD><EFBFBD> <20>׸<EFBFBD><D7B8><EFBFBD>.
DWORD colMark = posMark % MARK_COL_COUNT;
DWORD rowMark = posMark / MARK_COL_COUNT;
printf("PutMark pos %u %ux%u\n", posMark, colMark * SGuildMark::WIDTH, rowMark * SGuildMark::HEIGHT);
PutData(colMark * SGuildMark::WIDTH, rowMark * SGuildMark::HEIGHT, SGuildMark::WIDTH, SGuildMark::HEIGHT, pbImage);
// <20>׷<EFBFBD><D7B7><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ
DWORD rowBlock = rowMark / SGuildMarkBlock::MARK_PER_BLOCK_HEIGHT;
DWORD colBlock = colMark / SGuildMarkBlock::MARK_PER_BLOCK_WIDTH;
Pixel apxBuf[SGuildMarkBlock::SIZE];
GetData(colBlock * SGuildMarkBlock::WIDTH, rowBlock * SGuildMarkBlock::HEIGHT, SGuildMarkBlock::WIDTH, SGuildMarkBlock::HEIGHT, apxBuf);
m_aakBlock[rowBlock][colBlock].Compress(apxBuf);
return true;
}
bool CGuildMarkImage::DeleteMark(DWORD posMark)
{
Pixel image[SGuildMark::SIZE];
memset(&image, 0, sizeof(image));
return SaveMark(posMark, (BYTE *) &image);
}
// CLIENT
bool CGuildMarkImage::SaveBlockFromCompressedData(DWORD posBlock, const BYTE * pbComp, DWORD dwCompSize)
{
if (posBlock >= BLOCK_TOTAL_COUNT)
return false;
Pixel apxBuf[SGuildMarkBlock::SIZE];
lzo_uint sizeBuf = sizeof(apxBuf);
if (LZO_E_OK != lzo1x_decompress_safe(pbComp, dwCompSize, (BYTE *) apxBuf, &sizeBuf, CLZO::Instance().GetWorkMemory()))
{
sys_err("GuildMarkImage::CopyBlockFromCompressedData: cannot decompress, compressed size = %u", dwCompSize);
return false;
}
if (sizeBuf != sizeof(apxBuf))
{
sys_err("GuildMarkImage::CopyBlockFromCompressedData: image corrupted, decompressed size = %u", sizeBuf);
return false;
}
DWORD rowBlock = posBlock / BLOCK_COL_COUNT;
DWORD colBlock = posBlock % BLOCK_COL_COUNT;
PutData(colBlock * SGuildMarkBlock::WIDTH, rowBlock * SGuildMarkBlock::HEIGHT, SGuildMarkBlock::WIDTH, SGuildMarkBlock::HEIGHT, apxBuf);
m_aakBlock[rowBlock][colBlock].CopyFrom(pbComp, dwCompSize, GetCRC32((const char *) apxBuf, sizeof(Pixel) * SGuildMarkBlock::SIZE));
return true;
}
void CGuildMarkImage::BuildAllBlocks() // <20>̹<EFBFBD><CCB9><EFBFBD> <20><>ü<EFBFBD><C3BC> <20><><EFBFBD><EFBFBD>ȭ
{
Pixel apxBuf[SGuildMarkBlock::SIZE];
sys_log(0, "GuildMarkImage::BuildAllBlocks");
for (UINT row = 0; row < BLOCK_ROW_COUNT; ++row)
for (UINT col = 0; col < BLOCK_COL_COUNT; ++col)
{
GetData(col * SGuildMarkBlock::WIDTH, row * SGuildMarkBlock::HEIGHT, SGuildMarkBlock::WIDTH, SGuildMarkBlock::HEIGHT, apxBuf);
m_aakBlock[row][col].Compress(apxBuf);
}
}
DWORD CGuildMarkImage::GetEmptyPosition()
{
SGuildMark kMark;
for (DWORD row = 0; row < MARK_ROW_COUNT; ++row)
{
for (DWORD col = 0; col < MARK_COL_COUNT; ++col)
{
GetData(col * SGuildMark::WIDTH, row * SGuildMark::HEIGHT, SGuildMark::WIDTH, SGuildMark::HEIGHT, kMark.m_apxBuf);
if (kMark.IsEmpty())
return (row * MARK_COL_COUNT + col);
}
}
return INVALID_MARK_POSITION;
}
void CGuildMarkImage::GetDiffBlocks(const DWORD * crcList, std::map<BYTE, const SGuildMarkBlock *> & mapDiffBlocks)
{
BYTE posBlock = 0;
for (DWORD row = 0; row < BLOCK_ROW_COUNT; ++row)
for (DWORD col = 0; col < BLOCK_COL_COUNT; ++col)
{
if (m_aakBlock[row][col].m_crc != *crcList)
{
mapDiffBlocks.insert(std::map<BYTE, const SGuildMarkBlock *>::value_type(posBlock, &m_aakBlock[row][col]));
}
++crcList;
++posBlock;
}
}
void CGuildMarkImage::GetBlockCRCList(DWORD * crcList)
{
for (DWORD row = 0; row < BLOCK_ROW_COUNT; ++row)
for (DWORD col = 0; col < BLOCK_COL_COUNT; ++col)
*(crcList++) = m_aakBlock[row][col].GetCRC();
}
////////////////////////////////////////////////////////////////////////////////
void SGuildMark::Clear()
{
for (DWORD iPixel = 0; iPixel < SIZE; ++iPixel)
m_apxBuf[iPixel] = 0xff000000;
}
bool SGuildMark::IsEmpty()
{
for (DWORD iPixel = 0; iPixel < SIZE; ++iPixel)
if (m_apxBuf[iPixel] != 0x00000000)
return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////
DWORD SGuildMarkBlock::GetCRC() const
{
return m_crc;
}
void SGuildMarkBlock::CopyFrom(const BYTE * pbCompBuf, DWORD dwCompSize, DWORD crc)
{
if (dwCompSize > MAX_COMP_SIZE)
return;
m_sizeCompBuf = dwCompSize;
thecore_memcpy(m_abCompBuf, pbCompBuf, dwCompSize);
m_crc = crc;
//printf("SGuildMarkBlock::CopyFrom: %u > %u crc %u\n", sizeof(Pixel) * SGuildMarkBlock::SIZE, m_sizeCompBuf, m_crc);
}
void SGuildMarkBlock::Compress(const Pixel * pxBuf)
{
m_sizeCompBuf = MAX_COMP_SIZE;
if (LZO_E_OK != lzo1x_1_compress((const BYTE *) pxBuf, sizeof(Pixel) * SGuildMarkBlock::SIZE, m_abCompBuf, &m_sizeCompBuf, CLZO::Instance().GetWorkMemory()))
{
sys_err("SGuildMarkBlock::Compress: Error! %u > %u", sizeof(Pixel) * SGuildMarkBlock::SIZE, m_sizeCompBuf);
return;
}
//sys_log(0, "SGuildMarkBlock::Compress %u > %u", sizeof(Pixel) * SGuildMarkBlock::SIZE, m_sizeCompBuf);
m_crc = GetCRC32((const char *) pxBuf, sizeof(Pixel) * SGuildMarkBlock::SIZE);
}

111
game/src/MarkImage.h Normal file
View File

@ -0,0 +1,111 @@
#ifndef __INC_METIN_II_MARKIMAGE_H__
#define __INC_METIN_II_MARKIMAGE_H__
#include <IL/il.h>
#include "minilzo.h"
typedef unsigned long Pixel;
struct SGuildMark
{
enum
{
WIDTH = 16,
HEIGHT = 12,
SIZE = WIDTH * HEIGHT,
};
///////////////////////////////////////////////////////////////////////////////
Pixel m_apxBuf[SIZE]; // <20><><EFBFBD><EFBFBD> <20>̹<EFBFBD><CCB9><EFBFBD>
///////////////////////////////////////////////////////////////////////////////
void Clear();
bool IsEmpty();
};
struct SGuildMarkBlock
{
enum
{
MARK_PER_BLOCK_WIDTH = 4,
MARK_PER_BLOCK_HEIGHT = 4,
WIDTH = SGuildMark::WIDTH * MARK_PER_BLOCK_WIDTH,
HEIGHT = SGuildMark::HEIGHT * MARK_PER_BLOCK_HEIGHT,
SIZE = WIDTH * HEIGHT,
MAX_COMP_SIZE = (SIZE * sizeof(Pixel)) + ((SIZE * sizeof(Pixel)) >> 4) + 64 + 3
};
///////////////////////////////////////////////////////////////////////////////
Pixel m_apxBuf[SIZE]; // <20><><EFBFBD><EFBFBD> <20>̹<EFBFBD><CCB9><EFBFBD>
BYTE m_abCompBuf[MAX_COMP_SIZE]; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
lzo_uint m_sizeCompBuf; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ũ<><C5A9>
DWORD m_crc; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CRC
///////////////////////////////////////////////////////////////////////////////
DWORD GetCRC() const;
void CopyFrom(const BYTE * pbCompBuf, DWORD dwCompSize, DWORD crc);
void Compress(const Pixel * pxBuf);
};
class CGuildMarkImage
{
public:
enum
{
WIDTH = 512,
HEIGHT = 512,
BLOCK_ROW_COUNT = HEIGHT / SGuildMarkBlock::HEIGHT, // 10
BLOCK_COL_COUNT = WIDTH / SGuildMarkBlock::WIDTH, // 8
BLOCK_TOTAL_COUNT = BLOCK_ROW_COUNT * BLOCK_COL_COUNT, // 80
MARK_ROW_COUNT = BLOCK_ROW_COUNT * SGuildMarkBlock::MARK_PER_BLOCK_HEIGHT, // 40
MARK_COL_COUNT = BLOCK_COL_COUNT * SGuildMarkBlock::MARK_PER_BLOCK_WIDTH, // 32
MARK_TOTAL_COUNT = MARK_ROW_COUNT * MARK_COL_COUNT, // 1280
INVALID_MARK_POSITION = 0xffffffff,
};
CGuildMarkImage();
virtual ~CGuildMarkImage();
void Create();
void Destroy();
bool Build(const char * c_szFileName);
bool Save(const char* c_szFileName);
bool Load(const char* c_szFileName);
void PutData(UINT x, UINT y, UINT width, UINT height, void* data);
void GetData(UINT x, UINT y, UINT width, UINT height, void* data);
bool SaveMark(DWORD posMark, BYTE * pbMarkImage);
bool DeleteMark(DWORD posMark);
bool SaveBlockFromCompressedData(DWORD posBlock, const BYTE * pbComp, DWORD dwCompSize); // <20><><EFBFBD><EFBFBD> -> Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ
DWORD GetEmptyPosition(); // <20><> <20><>ũ <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD>´<EFBFBD>.
void GetBlockCRCList(DWORD * crcList);
void GetDiffBlocks(const DWORD * crcList, std::map<BYTE, const SGuildMarkBlock *> & mapDiffBlocks);
private:
enum
{
INVALID_HANDLE = 0xffffffff,
};
void BuildAllBlocks();
SGuildMarkBlock m_aakBlock[BLOCK_ROW_COUNT][BLOCK_COL_COUNT];
Pixel m_apxImage[WIDTH * HEIGHT * sizeof(Pixel)];
ILuint m_uImg;
};
#endif

473
game/src/MarkManager.cpp Normal file
View File

@ -0,0 +1,473 @@
#include "stdafx.h"
#include "MarkManager.h"
#include "crc32.h"
CGuildMarkImage * CGuildMarkManager::__NewImage()
{
return M2_NEW CGuildMarkImage;
}
void CGuildMarkManager::__DeleteImage(CGuildMarkImage * pkImgDel)
{
M2_DELETE(pkImgDel);
}
CGuildMarkManager::CGuildMarkManager()
{
// <20><><EFBFBD><EFBFBD> mark id <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
for (DWORD i = 0; i < MAX_IMAGE_COUNT * CGuildMarkImage::MARK_TOTAL_COUNT; ++i)
m_setFreeMarkID.insert(i);
}
CGuildMarkManager::~CGuildMarkManager()
{
for (std::map<DWORD, CGuildMarkImage *>::iterator it = m_mapIdx_Image.begin(); it != m_mapIdx_Image.end(); ++it)
__DeleteImage(it->second);
m_mapIdx_Image.clear();
}
bool CGuildMarkManager::GetMarkImageFilename(DWORD imgIdx, std::string & path) const
{
if (imgIdx >= MAX_IMAGE_COUNT)
return false;
char buf[64];
snprintf(buf, sizeof(buf), "mark/%s_%u.tga", m_pathPrefix.c_str(), imgIdx);
path = buf;
return true;
}
void CGuildMarkManager::SetMarkPathPrefix(const char * prefix)
{
m_pathPrefix = prefix;
}
// <20><>ũ <20>ε<EFBFBD><CEB5><EFBFBD> <20>ҷ<EFBFBD><D2B7><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
bool CGuildMarkManager::LoadMarkIndex()
{
char buf[64];
snprintf(buf, sizeof(buf), "mark/%s_index", m_pathPrefix.c_str());
FILE * fp = fopen(buf, "r");
if (!fp)
return false;
DWORD guildID;
DWORD markID;
char line[256];
while (fgets(line, sizeof(line)-1, fp))
{
sscanf(line, "%u %u", &guildID, &markID);
line[0] = '\0';
AddMarkIDByGuildID(guildID, markID);
}
LoadMarkImages();
fclose(fp);
return true;
}
bool CGuildMarkManager::SaveMarkIndex()
{
char buf[64];
snprintf(buf, sizeof(buf), "mark/%s_index", m_pathPrefix.c_str());
FILE * fp = fopen(buf, "w");
if (!fp)
{
sys_err("MarkManager::SaveMarkIndex: cannot open index file.");
return false;
}
for (std::map<DWORD, DWORD>::iterator it = m_mapGID_MarkID.begin(); it != m_mapGID_MarkID.end(); ++it)
fprintf(fp, "%u %u\n", it->first, it->second);
fclose(fp);
sys_log(0, "MarkManager::SaveMarkIndex: index count %d", m_mapGID_MarkID.size());
return true;
}
void CGuildMarkManager::LoadMarkImages()
{
bool isMarkExists[MAX_IMAGE_COUNT];
memset(isMarkExists, 0, sizeof(isMarkExists));
for (std::map<DWORD, DWORD>::iterator it = m_mapGID_MarkID.begin(); it != m_mapGID_MarkID.end(); ++it)
{
DWORD markID = it->second;
if (markID < MAX_IMAGE_COUNT * CGuildMarkImage::MARK_TOTAL_COUNT)
isMarkExists[markID / CGuildMarkImage::MARK_TOTAL_COUNT] = true;
}
for (DWORD i = 0; i < MAX_IMAGE_COUNT; ++i)
if (isMarkExists[i])
__GetImage(i);
}
void CGuildMarkManager::SaveMarkImage(DWORD imgIdx)
{
std::string path;
if (GetMarkImageFilename(imgIdx, path))
if (!__GetImage(imgIdx)->Save(path.c_str()))
sys_err("%s Save failed\n", path.c_str());
}
CGuildMarkImage * CGuildMarkManager::__GetImage(DWORD imgIdx)
{
std::map<DWORD, CGuildMarkImage *>::iterator it = m_mapIdx_Image.find(imgIdx);
if (it == m_mapIdx_Image.end())
{
std::string imagePath;
if (GetMarkImageFilename(imgIdx, imagePath))
{
CGuildMarkImage * pkImage = __NewImage();
m_mapIdx_Image.insert(std::map<DWORD, CGuildMarkImage *>::value_type(imgIdx, pkImage));
if (!pkImage->Load(imagePath.c_str()))
{
pkImage->Build(imagePath.c_str());
pkImage->Load(imagePath.c_str());
}
return pkImage;
}
else
return NULL;
}
else
return it->second;
}
bool CGuildMarkManager::AddMarkIDByGuildID(DWORD guildID, DWORD markID)
{
if (markID >= MAX_IMAGE_COUNT * CGuildMarkImage::MARK_TOTAL_COUNT)
return false;
//sys_log(0, "MarkManager: guild_id=%d mark_id=%d", guildID, markID);
m_mapGID_MarkID.insert(std::map<DWORD, DWORD>::value_type(guildID, markID));
m_setFreeMarkID.erase(markID);
return true;
}
DWORD CGuildMarkManager::GetMarkID(DWORD guildID)
{
std::map<DWORD, DWORD>::iterator it = m_mapGID_MarkID.find(guildID);
if (it == m_mapGID_MarkID.end())
return INVALID_MARK_ID;
return it->second;
}
DWORD CGuildMarkManager::__AllocMarkID(DWORD guildID)
{
std::set<DWORD>::iterator it = m_setFreeMarkID.lower_bound(0);
if (it == m_setFreeMarkID.end())
return INVALID_MARK_ID;
DWORD markID = *it;
DWORD imgIdx = markID / CGuildMarkImage::MARK_TOTAL_COUNT;
CGuildMarkImage * pkImage = __GetImage(imgIdx); // <20>̹<EFBFBD><CCB9><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ٸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
if (pkImage && AddMarkIDByGuildID(guildID, markID))
return markID;
return INVALID_MARK_ID;
}
DWORD CGuildMarkManager::GetMarkImageCount() const
{
return m_mapIdx_Image.size();
}
DWORD CGuildMarkManager::GetMarkCount() const
{
return m_mapGID_MarkID.size();
}
// SERVER
void CGuildMarkManager::CopyMarkIdx(char * pcBuf) const
{
WORD * pwBuf = (WORD *) pcBuf;
for (std::map<DWORD, DWORD>::const_iterator it = m_mapGID_MarkID.begin(); it != m_mapGID_MarkID.end(); ++it)
{
*(pwBuf++) = it->first; // guild id
*(pwBuf++) = it->second; // mark id
}
}
// SERVER
DWORD CGuildMarkManager::SaveMark(DWORD guildID, BYTE * pbMarkImage)
{
DWORD idMark;
if ((idMark = GetMarkID(guildID)) == INVALID_MARK_ID)
{
if ((idMark = __AllocMarkID(guildID)) == INVALID_MARK_ID)
{
sys_err("CGuildMarkManager: cannot alloc mark id %u", guildID);
return false;
}
else
sys_log(0, "SaveMark: mark id alloc %u", idMark);
}
else
sys_log(0, "SaveMark: mark id found %u", idMark);
DWORD imgIdx = (idMark / CGuildMarkImage::MARK_TOTAL_COUNT);
CGuildMarkImage * pkImage = __GetImage(imgIdx);
if (pkImage)
{
pkImage->SaveMark(idMark % CGuildMarkImage::MARK_TOTAL_COUNT, pbMarkImage);
SaveMarkImage(imgIdx);
SaveMarkIndex();
}
return idMark;
}
// SERVER
void CGuildMarkManager::DeleteMark(DWORD guildID)
{
std::map<DWORD, DWORD>::iterator it = m_mapGID_MarkID.find(guildID);
if (it == m_mapGID_MarkID.end())
return;
CGuildMarkImage * pkImage;
if ((pkImage = __GetImage(it->second / CGuildMarkImage::MARK_TOTAL_COUNT)) != NULL)
pkImage->DeleteMark(it->second % CGuildMarkImage::MARK_TOTAL_COUNT);
m_setFreeMarkID.insert(it->second);
m_mapGID_MarkID.erase(it);
SaveMarkIndex();
}
// SERVER
void CGuildMarkManager::GetDiffBlocks(DWORD imgIdx, const DWORD * crcList, std::map<BYTE, const SGuildMarkBlock *> & mapDiffBlocks)
{
mapDiffBlocks.clear();
// Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>̹<EFBFBD><CCB9><EFBFBD><EFBFBD><EFBFBD> <20><>û<EFBFBD><C3BB> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
if (m_mapIdx_Image.end() == m_mapIdx_Image.find(imgIdx))
{
sys_err("invalid idx %u", imgIdx);
return;
}
CGuildMarkImage * p = __GetImage(imgIdx);
if (p)
p->GetDiffBlocks(crcList, mapDiffBlocks);
}
// CLIENT
bool CGuildMarkManager::SaveBlockFromCompressedData(DWORD imgIdx, DWORD posBlock, const BYTE * pbBlock, DWORD dwSize)
{
CGuildMarkImage * pkImage = __GetImage(imgIdx);
if (pkImage)
pkImage->SaveBlockFromCompressedData(posBlock, pbBlock, dwSize);
return false;
}
// CLIENT
bool CGuildMarkManager::GetBlockCRCList(DWORD imgIdx, DWORD * crcList)
{
// Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>̹<EFBFBD><CCB9><EFBFBD><EFBFBD><EFBFBD> <20><>û<EFBFBD><C3BB> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
if (m_mapIdx_Image.end() == m_mapIdx_Image.find(imgIdx))
{
sys_err("invalid idx %u", imgIdx);
return false;
}
CGuildMarkImage * p = __GetImage(imgIdx);
if (p)
p->GetBlockCRCList(crcList);
return true;
}
///////////////////////////////////////////////////////////////////////////////////////
// Symbol
///////////////////////////////////////////////////////////////////////////////////////
const CGuildMarkManager::TGuildSymbol * CGuildMarkManager::GetGuildSymbol(DWORD guildID)
{
std::map<DWORD, TGuildSymbol>::iterator it = m_mapSymbol.find(guildID);
if (it == m_mapSymbol.end())
return NULL;
return &it->second;
}
bool CGuildMarkManager::LoadSymbol(const char* filename)
{
FILE* fp = fopen(filename, "rb");
if (!fp)
return true;
else
{
DWORD symbolCount;
fread(&symbolCount, 4, 1, fp);
for (DWORD i = 0; i < symbolCount; i++)
{
DWORD guildID;
DWORD dwSize;
fread(&guildID, 4, 1, fp);
fread(&dwSize, 4, 1, fp);
TGuildSymbol gs;
gs.raw.resize(dwSize);
fread(&gs.raw[0], 1, dwSize, fp);
gs.crc = GetCRC32(reinterpret_cast<const char*>(&gs.raw[0]), dwSize);
m_mapSymbol.insert(std::make_pair(guildID, gs));
}
}
fclose(fp);
return true;
}
void CGuildMarkManager::SaveSymbol(const char* filename)
{
FILE* fp = fopen(filename, "wb");
if (!fp)
{
sys_err("Cannot open Symbol file (name: %s)", filename);
return;
}
DWORD symbolCount = m_mapSymbol.size();
fwrite(&symbolCount, 4, 1, fp);
for (std::map<DWORD, TGuildSymbol>::iterator it = m_mapSymbol.begin(); it != m_mapSymbol.end(); ++it)
{
DWORD guildID = it->first;
DWORD dwSize = it->second.raw.size();
fwrite(&guildID, 4, 1, fp);
fwrite(&dwSize, 4, 1, fp);
fwrite(&it->second.raw[0], 1, dwSize, fp);
}
fclose(fp);
}
void CGuildMarkManager::UploadSymbol(DWORD guildID, int iSize, const BYTE* pbyData)
{
sys_log(0, "GuildSymbolUpload guildID %u Size %d", guildID, iSize);
if (m_mapSymbol.find(guildID) == m_mapSymbol.end())
m_mapSymbol.insert(std::make_pair(guildID, TGuildSymbol()));
TGuildSymbol& rSymbol = m_mapSymbol[guildID];
rSymbol.raw.clear();
if (iSize > 0)
{
rSymbol.raw.reserve(iSize);
std::copy(pbyData, (pbyData + iSize), std::back_inserter(rSymbol.raw));
rSymbol.crc = GetCRC32(reinterpret_cast<const char*>(pbyData), iSize);
}
}
#ifdef __UNITTEST__
#include "lzo_manager.h"
void heartbeat(LPHEART ht, int pulse)
{
return;
}
void SaveMark(DWORD guildID, const char * filename)
{
ILuint m_uImg;
ilGenImages(1, &m_uImg);
ilBindImage(m_uImg);
ilEnable(IL_ORIGIN_SET);
ilOriginFunc(IL_ORIGIN_UPPER_LEFT);
if (ilLoad(IL_TYPE_UNKNOWN, (const ILstring) filename))
{
ILuint width = ilGetInteger(IL_IMAGE_WIDTH);
ILuint height = ilGetInteger(IL_IMAGE_HEIGHT);
ilConvertImage(IL_BGRA, IL_UNSIGNED_BYTE);
BYTE * data = (BYTE *) malloc(sizeof(DWORD) * width * height);
ilCopyPixels(0, 0, 0, width, height, 1, IL_BGRA, IL_UNSIGNED_BYTE, data);
ilDeleteImages(1, &m_uImg);
printf("%s w%u h%u ", filename, width, height);
CGuildMarkManager::instance().SaveMark(guildID, data);
}
else
printf("%s cannot open file.\n", filename);
}
int main(int argc, char **argv)
{
LZOManager lzo;
CGuildMarkManager mgr;
char f[64];
srandomdev();
ilInit(); // DevIL Initialize
thecore_init(25, heartbeat);
mgr.SetMarkPathPrefix("mark");
mgr.LoadMarkIndex();
for (int i = 0; i < 1279; ++i)
{
snprintf(f, sizeof(f), "%u.jpg", (random() % 5) + 1);
SaveMark(i, f);
//mgr.DeleteMark(i);
}
//snprintf(f, sizeof(f), "%u.jpg", (random() % 5) + 1);
//SaveMark(1, f);
DWORD idx_client[CGuildMarkImage::BLOCK_TOTAL_COUNT];
DWORD idx_server[CGuildMarkImage::BLOCK_TOTAL_COUNT];
mgr.GetBlockCRCList(0, idx_client);
mgr.GetBlockCRCList(1, idx_server);
std::map<BYTE, const SGuildMarkBlock *> mapDiff;
mgr.GetDiffBlocks(1, idx_client, mapDiff);
printf("#1 Diff %u\n", mapDiff.size());
for (itertype(mapDiff) it = mapDiff.begin(); it != mapDiff.end(); ++it)
{
printf("Put Block pos %u crc %u\n", it->first, it->second->m_crc);
mgr.SaveBlockFromCompressedData(0, it->first, it->second->m_abCompBuf, it->second->m_sizeCompBuf);
}
mgr.GetBlockCRCList(0, idx_client);
mgr.GetDiffBlocks(1, idx_client, mapDiff);
printf("#2 Diff %u\n", mapDiff.size());
return 1;
}
#endif

82
game/src/MarkManager.h Normal file
View File

@ -0,0 +1,82 @@
#ifndef __INC_METIN_II_GUILDLIB_MARK_MANAGER_H__
#define __INC_METIN_II_GUILDLIB_MARK_MANAGER_H__
#include "MarkImage.h"
class CGuildMarkManager : public singleton<CGuildMarkManager>
{
public:
enum
{
MAX_IMAGE_COUNT = 5,
INVALID_MARK_ID = 0xffffffff,
};
// Symbol
struct TGuildSymbol
{
DWORD crc;
std::vector<BYTE> raw;
};
CGuildMarkManager();
virtual ~CGuildMarkManager();
const TGuildSymbol * GetGuildSymbol(DWORD GID);
bool LoadSymbol(const char* filename);
void SaveSymbol(const char* filename);
void UploadSymbol(DWORD guildID, int iSize, const BYTE* pbyData);
//
// Mark
//
void SetMarkPathPrefix(const char * prefix);
bool LoadMarkIndex(); // <20><>ũ <20>ε<EFBFBD><CEB5><EFBFBD> <20>ҷ<EFBFBD><D2B7><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
bool SaveMarkIndex(); // <20><>ũ <20>ε<EFBFBD><CEB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD>
void LoadMarkImages(); // <20><><EFBFBD><EFBFBD> <20><>ũ <20>̹<EFBFBD><CCB9><EFBFBD><EFBFBD><EFBFBD> <20>ҷ<EFBFBD><D2B7><EFBFBD><EFBFBD><EFBFBD>
void SaveMarkImage(DWORD imgIdx); // <20><>ũ <20>̹<EFBFBD><CCB9><EFBFBD> <20><><EFBFBD><EFBFBD>
bool GetMarkImageFilename(DWORD imgIdx, std::string & path) const;
bool AddMarkIDByGuildID(DWORD guildID, DWORD markID);
DWORD GetMarkImageCount() const;
DWORD GetMarkCount() const;
DWORD GetMarkID(DWORD guildID);
// SERVER
void CopyMarkIdx(char * pcBuf) const;
DWORD SaveMark(DWORD guildID, BYTE * pbMarkImage);
void DeleteMark(DWORD guildID);
void GetDiffBlocks(DWORD imgIdx, const DWORD * crcList, std::map<BYTE, const SGuildMarkBlock *> & mapDiffBlocks);
// CLIENT
bool SaveBlockFromCompressedData(DWORD imgIdx, DWORD idBlock, const BYTE * pbBlock, DWORD dwSize);
bool GetBlockCRCList(DWORD imgIdx, DWORD * crcList);
private:
//
// Mark
//
CGuildMarkImage * __NewImage();
void __DeleteImage(CGuildMarkImage * pkImgDel);
DWORD __AllocMarkID(DWORD guildID);
CGuildMarkImage * __GetImage(DWORD imgIdx);
CGuildMarkImage * __GetImagePtr(DWORD idMark);
std::map<DWORD, CGuildMarkImage *> m_mapIdx_Image; // index = image index
std::map<DWORD, DWORD> m_mapGID_MarkID; // index = guild id
std::set<DWORD> m_setFreeMarkID;
std::string m_pathPrefix;
private:
//
// Symbol
//
std::map<DWORD, TGuildSymbol> m_mapSymbol;
};
#endif

441
game/src/OXEvent.cpp Normal file
View File

@ -0,0 +1,441 @@
#include "stdafx.h"
#include "constants.h"
#include "config.h"
#include "questmanager.h"
#include "start_position.h"
#include "packet.h"
#include "buffer_manager.h"
#include "log.h"
#include "char.h"
#include "char_manager.h"
#include "OXEvent.h"
#include "desc.h"
bool COXEventManager::Initialize()
{
m_timedEvent = NULL;
m_map_char.clear();
m_map_attender.clear();
m_vec_quiz.clear();
SetStatus(OXEVENT_FINISH);
return true;
}
void COXEventManager::Destroy()
{
CloseEvent();
m_map_char.clear();
m_map_attender.clear();
m_vec_quiz.clear();
SetStatus(OXEVENT_FINISH);
}
OXEventStatus COXEventManager::GetStatus()
{
BYTE ret = quest::CQuestManager::instance().GetEventFlag("oxevent_status");
switch (ret)
{
case 0 :
return OXEVENT_FINISH;
case 1 :
return OXEVENT_OPEN;
case 2 :
return OXEVENT_CLOSE;
case 3 :
return OXEVENT_QUIZ;
default :
return OXEVENT_ERR;
}
return OXEVENT_ERR;
}
void COXEventManager::SetStatus(OXEventStatus status)
{
BYTE val = 0;
switch (status)
{
case OXEVENT_OPEN :
val = 1;
break;
case OXEVENT_CLOSE :
val = 2;
break;
case OXEVENT_QUIZ :
val = 3;
break;
case OXEVENT_FINISH :
case OXEVENT_ERR :
default :
val = 0;
break;
}
quest::CQuestManager::instance().RequestSetEventFlag("oxevent_status", val);
}
bool COXEventManager::Enter(LPCHARACTER pkChar)
{
if (GetStatus() == OXEVENT_FINISH)
{
sys_log(0, "OXEVENT : map finished. but char enter. %s", pkChar->GetName());
return false;
}
PIXEL_POSITION pos = pkChar->GetXYZ();
if (pos.x == 896500 && pos.y == 24600)
{
return EnterAttender(pkChar);
}
else if (pos.x == 896300 && pos.y == 28900)
{
return EnterAudience(pkChar);
}
else
{
sys_log(0, "OXEVENT : wrong pos enter %d %d", pos.x, pos.y);
return false;
}
return false;
}
bool COXEventManager::EnterAttender(LPCHARACTER pkChar)
{
DWORD pid = pkChar->GetPlayerID();
m_map_char.insert(std::make_pair(pid, pid));
m_map_attender.insert(std::make_pair(pid, pid));
return true;
}
bool COXEventManager::EnterAudience(LPCHARACTER pkChar)
{
DWORD pid = pkChar->GetPlayerID();
m_map_char.insert(std::make_pair(pid, pid));
return true;
}
bool COXEventManager::AddQuiz(unsigned char level, const char* pszQuestion, bool answer)
{
if (m_vec_quiz.size() < (size_t) level + 1)
m_vec_quiz.resize(level + 1);
struct tag_Quiz tmpQuiz;
tmpQuiz.level = level;
strlcpy(tmpQuiz.Quiz, pszQuestion, sizeof(tmpQuiz.Quiz));
tmpQuiz.answer = answer;
m_vec_quiz[level].push_back(tmpQuiz);
return true;
}
bool COXEventManager::ShowQuizList(LPCHARACTER pkChar)
{
int c = 0;
for (size_t i = 0; i < m_vec_quiz.size(); ++i)
{
for (size_t j = 0; j < m_vec_quiz[i].size(); ++j, ++c)
{
pkChar->ChatPacket(CHAT_TYPE_INFO, "%d %s %s", m_vec_quiz[i][j].level, m_vec_quiz[i][j].Quiz, m_vec_quiz[i][j].answer ? LC_TEXT("<EFBFBD><EFBFBD>") : LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
}
}
pkChar->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>: %d"), c);
return true;
}
void COXEventManager::ClearQuiz()
{
for (unsigned int i = 0; i < m_vec_quiz.size(); ++i)
{
m_vec_quiz[i].clear();
}
m_vec_quiz.clear();
}
EVENTINFO(OXEventInfoData)
{
bool answer;
OXEventInfoData()
: answer( false )
{
}
};
EVENTFUNC(oxevent_timer)
{
static BYTE flag = 0;
OXEventInfoData* info = dynamic_cast<OXEventInfoData*>(event->info);
if ( info == NULL )
{
sys_err( "oxevent_timer> <Factor> Null pointer" );
return 0;
}
switch (flag)
{
case 0:
SendNoticeMap(LC_TEXT("10<EFBFBD>ʵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰڽ<CFB0><DABD>ϴ<EFBFBD>."), OXEVENT_MAP_INDEX, true);
flag++;
return PASSES_PER_SEC(10);
case 1:
SendNoticeMap(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), OXEVENT_MAP_INDEX, true);
if (info->answer == true)
{
COXEventManager::instance().CheckAnswer(true);
SendNoticeMap(LC_TEXT("O <20>Դϴ<D4B4>"), OXEVENT_MAP_INDEX, true);
}
else
{
COXEventManager::instance().CheckAnswer(false);
SendNoticeMap(LC_TEXT("X <20>Դϴ<D4B4>"), OXEVENT_MAP_INDEX, true);
}
if (LC_IsJapan())
{
SendNoticeMap("<EFBFBD>ԈႦ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>X<EFBFBD><EFBFBD><EFBFBD>O<EFBFBD>Ɉړ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><EFBFBD>B", OXEVENT_MAP_INDEX, true);
}
else
{
SendNoticeMap(LC_TEXT("5<EFBFBD><EFBFBD> <20><> Ʋ<><C6B2><EFBFBD><EFBFBD> <20>е<EFBFBD><D0B5><EFBFBD> <20>ٱ<EFBFBD><D9B1><EFBFBD><EFBFBD><EFBFBD> <20>̵<EFBFBD> <20><>Ű<EFBFBD>ڽ<EFBFBD><DABD>ϴ<EFBFBD>."), OXEVENT_MAP_INDEX, true);
}
flag++;
return PASSES_PER_SEC(5);
case 2:
COXEventManager::instance().WarpToAudience();
COXEventManager::instance().SetStatus(OXEVENT_CLOSE);
SendNoticeMap(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>غ<EFBFBD><D8BA><EFBFBD><EFBFBD>ּ<EFBFBD><D6BC><EFBFBD>."), OXEVENT_MAP_INDEX, true);
flag = 0;
break;
}
return 0;
}
bool COXEventManager::Quiz(unsigned char level, int timelimit)
{
if (m_vec_quiz.size() == 0) return false;
if (level > m_vec_quiz.size()) level = m_vec_quiz.size() - 1;
if (m_vec_quiz[level].size() <= 0) return false;
if (timelimit < 0) timelimit = 30;
int idx = number(0, m_vec_quiz[level].size()-1);
SendNoticeMap(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Դϴ<D4B4>."), OXEVENT_MAP_INDEX, true);
SendNoticeMap(m_vec_quiz[level][idx].Quiz, OXEVENT_MAP_INDEX, true);
SendNoticeMap(LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> O, Ʋ<><C6B2><EFBFBD><EFBFBD> X<><58> <20>̵<EFBFBD><CCB5><EFBFBD><EFBFBD>ּ<EFBFBD><D6BC><EFBFBD>"), OXEVENT_MAP_INDEX, true);
if (m_timedEvent != NULL) {
event_cancel(&m_timedEvent);
}
OXEventInfoData* answer = AllocEventInfo<OXEventInfoData>();
answer->answer = m_vec_quiz[level][idx].answer;
timelimit -= 15;
m_timedEvent = event_create(oxevent_timer, answer, PASSES_PER_SEC(timelimit));
SetStatus(OXEVENT_QUIZ);
m_vec_quiz[level].erase(m_vec_quiz[level].begin()+idx);
return true;
}
bool COXEventManager::CheckAnswer(bool answer)
{
if (m_map_attender.size() <= 0) return true;
itertype(m_map_attender) iter = m_map_attender.begin();
itertype(m_map_attender) iter_tmp;
m_map_miss.clear();
int rect[4];
if (answer != true)
{
rect[0] = 892600;
rect[1] = 22900;
rect[2] = 896300;
rect[3] = 26400;
}
else
{
rect[0] = 896600;
rect[1] = 22900;
rect[2] = 900300;
rect[3] = 26400;
}
LPCHARACTER pkChar = NULL;
PIXEL_POSITION pos;
for (; iter != m_map_attender.end();)
{
pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
if (pkChar != NULL)
{
pos = pkChar->GetXYZ();
if (pos.x < rect[0] || pos.x > rect[2] || pos.y < rect[1] || pos.y > rect[3])
{
pkChar->EffectPacket(SE_FAIL);
iter_tmp = iter;
iter++;
m_map_attender.erase(iter_tmp);
m_map_miss.insert(std::make_pair(pkChar->GetPlayerID(), pkChar->GetPlayerID()));
}
else
{
pkChar->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դϴ<EFBFBD>!"));
// pkChar->CreateFly(number(FLY_FIREWORK1, FLY_FIREWORK6), pkChar);
char chatbuf[256];
int len = snprintf(chatbuf, sizeof(chatbuf),
"%s %u %u", number(0, 1) == 1 ? "cheer1" : "cheer2", (DWORD)pkChar->GetVID(), 0);
// <20><><EFBFBD>ϰ<EFBFBD><CFB0><EFBFBD> sizeof(chatbuf) <20>̻<EFBFBD><CCBB><EFBFBD> <20><><EFBFBD><EFBFBD> truncate<74>Ǿ<EFBFBD><C7BE>ٴ<EFBFBD> <20><>..
if (len < 0 || len >= (int) sizeof(chatbuf))
len = sizeof(chatbuf) - 1;
// \0 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
++len;
TPacketGCChat pack_chat;
pack_chat.header = HEADER_GC_CHAT;
pack_chat.size = sizeof(TPacketGCChat) + len;
pack_chat.type = CHAT_TYPE_COMMAND;
pack_chat.id = 0;
TEMP_BUFFER buf;
buf.write(&pack_chat, sizeof(TPacketGCChat));
buf.write(chatbuf, len);
pkChar->PacketAround(buf.read_peek(), buf.size());
pkChar->EffectPacket(SE_SUCCESS);
++iter;
}
}
else
{
itertype(m_map_char) err = m_map_char.find(iter->first);
if (err != m_map_char.end()) m_map_char.erase(err);
itertype(m_map_miss) err2 = m_map_miss.find(iter->first);
if (err2 != m_map_miss.end()) m_map_miss.erase(err2);
iter_tmp = iter;
++iter;
m_map_attender.erase(iter_tmp);
}
}
return true;
}
void COXEventManager::WarpToAudience()
{
if (m_map_miss.size() <= 0) return;
itertype(m_map_miss) iter = m_map_miss.begin();
LPCHARACTER pkChar = NULL;
for (; iter != m_map_miss.end(); ++iter)
{
pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
if (pkChar != NULL)
{
switch ( number(0, 3))
{
case 0 : pkChar->Show(OXEVENT_MAP_INDEX, 896300, 28900); break;
case 1 : pkChar->Show(OXEVENT_MAP_INDEX, 890900, 28100); break;
case 2 : pkChar->Show(OXEVENT_MAP_INDEX, 896600, 20500); break;
case 3 : pkChar->Show(OXEVENT_MAP_INDEX, 902500, 28100); break;
default : pkChar->Show(OXEVENT_MAP_INDEX, 896300, 28900); break;
}
}
}
m_map_miss.clear();
}
bool COXEventManager::CloseEvent()
{
if (m_timedEvent != NULL) {
event_cancel(&m_timedEvent);
}
itertype(m_map_char) iter = m_map_char.begin();
LPCHARACTER pkChar = NULL;
for (; iter != m_map_char.end(); ++iter)
{
pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
if (pkChar != NULL)
pkChar->WarpSet(EMPIRE_START_X(pkChar->GetEmpire()), EMPIRE_START_Y(pkChar->GetEmpire()));
}
m_map_char.clear();
return true;
}
bool COXEventManager::LogWinner()
{
itertype(m_map_attender) iter = m_map_attender.begin();
for (; iter != m_map_attender.end(); ++iter)
{
LPCHARACTER pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
if (pkChar)
LogManager::instance().CharLog(pkChar, 0, "OXEVENT", "LastManStanding");
}
return true;
}
bool COXEventManager::GiveItemToAttender(DWORD dwItemVnum, BYTE count)
{
itertype(m_map_attender) iter = m_map_attender.begin();
for (; iter != m_map_attender.end(); ++iter)
{
LPCHARACTER pkChar = CHARACTER_MANAGER::instance().FindByPID(iter->second);
if (pkChar)
{
pkChar->AutoGiveItem(dwItemVnum, count);
LogManager::instance().ItemLog(pkChar->GetPlayerID(), 0, count, dwItemVnum, "OXEVENT_REWARD", "", pkChar->GetDesc()->GetHostName(), dwItemVnum);
}
}
return true;
}

65
game/src/OXEvent.h Normal file
View File

@ -0,0 +1,65 @@
#define OXEVENT_MAP_INDEX 113
struct tag_Quiz
{
char level;
char Quiz[256];
bool answer;
};
enum OXEventStatus
{
OXEVENT_FINISH = 0, // OX<4F>̺<EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
OXEVENT_OPEN = 1, // OX<4F>̺<EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD>۵<EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(20012)<29><> <20><><EFBFBD>ؼ<EFBFBD> <20><><EFBFBD><EFBFBD><E5B0A1>
OXEVENT_CLOSE = 2, // OX<4F>̺<EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(20012)<29><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ܵ<EFBFBD>
OXEVENT_QUIZ = 3, // <20><><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
OXEVENT_ERR = 0xff
};
class COXEventManager : public singleton<COXEventManager>
{
private :
std::map<DWORD, DWORD> m_map_char;
std::map<DWORD, DWORD> m_map_attender;
std::map<DWORD, DWORD> m_map_miss;
std::vector<std::vector<tag_Quiz> > m_vec_quiz;
LPEVENT m_timedEvent;
protected :
bool CheckAnswer();
bool EnterAudience(LPCHARACTER pChar);
bool EnterAttender(LPCHARACTER pChar);
public :
bool Initialize();
void Destroy();
OXEventStatus GetStatus();
void SetStatus(OXEventStatus status);
bool LoadQuizScript(const char* szFileName);
bool Enter(LPCHARACTER pChar);
bool CloseEvent();
void ClearQuiz();
bool AddQuiz(unsigned char level, const char* pszQuestion, bool answer);
bool ShowQuizList(LPCHARACTER pChar);
bool Quiz(unsigned char level, int timelimit);
bool GiveItemToAttender(DWORD dwItemVnum, BYTE count);
bool CheckAnswer(bool answer);
void WarpToAudience();
bool LogWinner();
DWORD GetAttenderCount() { return m_map_attender.size(); }
};

637
game/src/PetSystem.cpp Normal file
View File

@ -0,0 +1,637 @@
#include "stdafx.h"
#include "utils.h"
#include "vector.h"
#include "char.h"
#include "sectree_manager.h"
#include "char_manager.h"
#include "mob_manager.h"
#include "PetSystem.h"
#include "../../common/VnumHelper.h"
#include "packet.h"
#include "item_manager.h"
#include "item.h"
extern int passes_per_sec;
EVENTINFO(petsystem_event_info)
{
CPetSystem* pPetSystem;
};
// PetSystem<65><6D> update <20><><EFBFBD>ִ<EFBFBD> event.
// PetSystem<65><6D> CHRACTER_MANAGER<45><52><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> FSM<53><4D><EFBFBD><EFBFBD> update <20><><EFBFBD>ִ<EFBFBD> <20><><EFBFBD><EFBFBD> chracters<72><73> <20>޸<EFBFBD>,
// Owner<65><72> STATE<54><45> update <20><> <20><> _UpdateFollowAI <20>Լ<EFBFBD><D4BC><EFBFBD> update <20><><EFBFBD>ش<EFBFBD>.
// <20>׷<EFBFBD><D7B7><EFBFBD> owner<65><72> state<74><65> update<74><65> CHRACTER_MANAGER<45><52><EFBFBD><EFBFBD> <20><><EFBFBD>ֱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,
// petsystem<65><6D> update<74>ϴٰ<CFB4> pet<65><74> unsummon<6F>ϴ<EFBFBD> <20>κп<CEBA><D0BF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
// (CHRACTER_MANAGER<45><52><EFBFBD><EFBFBD> update <20>ϸ<EFBFBD> chracter destroy<6F><79> pending<6E>Ǿ<EFBFBD>, CPetSystem<65><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD> dangling <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ְ<EFBFBD> <20>ȴ<EFBFBD>.)
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> PetSystem<65><6D> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD>ִ<EFBFBD> event<6E><74> <20>߻<EFBFBD><DFBB><EFBFBD>Ŵ.
EVENTFUNC(petsystem_update_event)
{
petsystem_event_info* info = dynamic_cast<petsystem_event_info*>( event->info );
if ( info == NULL )
{
sys_err( "check_speedhack_event> <Factor> Null pointer" );
return 0;
}
CPetSystem* pPetSystem = info->pPetSystem;
if (NULL == pPetSystem)
return 0;
pPetSystem->Update(0);
// 0.25<EFBFBD>ʸ<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
return PASSES_PER_SEC(1) / 4;
}
/// NOTE: 1ij<31><C4B3><EFBFBD>Ͱ<EFBFBD> <20><EFBFBD><EEB0B3> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD><D6B4><EFBFBD> <20><><EFBFBD><EFBFBD>... ij<><C4B3><EFBFBD>͸<EFBFBD><CDB8><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٸ<EFBFBD><D9B8><EFBFBD> <20>ҰŶ<D2B0><C5B6><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֵ... <20><>..
/// <20><><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ÿ<EFBFBD> <20><>ȯ<EFBFBD><C8AF> <20><> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ʋ<><C6B2> <20><> <20>ִµ<D6B4> <20>̷<EFBFBD><CCB7><EFBFBD> <20><>ȹ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD>
const float PET_COUNT_LIMIT = 3;
///////////////////////////////////////////////////////////////////////////////////////
// CPetActor
///////////////////////////////////////////////////////////////////////////////////////
CPetActor::CPetActor(LPCHARACTER owner, DWORD vnum, DWORD options)
{
m_dwVnum = vnum;
m_dwVID = 0;
m_dwOptions = options;
m_dwLastActionTime = 0;
m_pkChar = 0;
m_pkOwner = owner;
m_originalMoveSpeed = 0;
m_dwSummonItemVID = 0;
m_dwSummonItemVnum = 0;
}
CPetActor::~CPetActor()
{
this->Unsummon();
m_pkOwner = 0;
}
void CPetActor::SetName(const char* name)
{
std::string petName = m_pkOwner->GetName();
if (0 != m_pkOwner &&
0 == name &&
0 != m_pkOwner->GetName())
{
petName += "'s Pet";
}
else
petName += name;
if (true == IsSummoned())
m_pkChar->SetName(petName);
m_name = petName;
}
bool CPetActor::Mount()
{
if (0 == m_pkOwner)
return false;
if (true == HasOption(EPetOption_Mountable))
m_pkOwner->MountVnum(m_dwVnum);
return m_pkOwner->GetMountVnum() == m_dwVnum;;
}
void CPetActor::Unmount()
{
if (0 == m_pkOwner)
return;
if (m_pkOwner->IsHorseRiding())
m_pkOwner->StopRiding();
}
void CPetActor::Unsummon()
{
if (true == this->IsSummoned())
{
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
this->ClearBuff();
this->SetSummonItem(NULL);
if (NULL != m_pkOwner)
m_pkOwner->ComputePoints();
if (NULL != m_pkChar)
M2_DESTROY_CHARACTER(m_pkChar);
m_pkChar = 0;
m_dwVID = 0;
}
}
DWORD CPetActor::Summon(const char* petName, LPITEM pSummonItem, bool bSpawnFar)
{
long x = m_pkOwner->GetX();
long y = m_pkOwner->GetY();
long z = m_pkOwner->GetZ();
if (true == bSpawnFar)
{
x += (number(0, 1) * 2 - 1) * number(2000, 2500);
y += (number(0, 1) * 2 - 1) * number(2000, 2500);
}
else
{
x += number(-100, 100);
y += number(-100, 100);
}
if (0 != m_pkChar)
{
m_pkChar->Show (m_pkOwner->GetMapIndex(), x, y);
m_dwVID = m_pkChar->GetVID();
return m_dwVID;
}
m_pkChar = CHARACTER_MANAGER::instance().SpawnMob(
m_dwVnum,
m_pkOwner->GetMapIndex(),
x, y, z,
false, (int)(m_pkOwner->GetRotation()+180), false);
if (0 == m_pkChar)
{
sys_err("[CPetSystem::Summon] Failed to summon the pet. (vnum: %d)", m_dwVnum);
return 0;
}
m_pkChar->SetPet();
// m_pkOwner->DetailLog();
// m_pkChar->DetailLog();
//<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
m_pkChar->SetEmpire(m_pkOwner->GetEmpire());
m_dwVID = m_pkChar->GetVID();
this->SetName(petName);
// SetSummonItem(pSummonItem)<29><> <20>θ<EFBFBD> <20>Ŀ<EFBFBD> ComputePoints<74><73> <20>θ<EFBFBD><CEB8><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
this->SetSummonItem(pSummonItem);
m_pkOwner->ComputePoints();
m_pkChar->Show(m_pkOwner->GetMapIndex(), x, y, z);
return m_dwVID;
}
bool CPetActor::_UpdatAloneActionAI(float fMinDist, float fMaxDist)
{
float fDist = number(fMinDist, fMaxDist);
float r = (float)number (0, 359);
float dest_x = GetOwner()->GetX() + fDist * cos(r);
float dest_y = GetOwner()->GetY() + fDist * sin(r);
//m_pkChar->SetRotation(number(0, 359)); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
//GetDeltaByDegree(m_pkChar->GetRotation(), fDist, &fx, &fy);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ӽ<EFBFBD> üũ; <20><><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> <20>߰<EFBFBD> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٸ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
//if (!(SECTREE_MANAGER::instance().IsMovablePosition(m_pkChar->GetMapIndex(), m_pkChar->GetX() + (int) fx, m_pkChar->GetY() + (int) fy)
// && SECTREE_MANAGER::instance().IsMovablePosition(m_pkChar->GetMapIndex(), m_pkChar->GetX() + (int) fx/2, m_pkChar->GetY() + (int) fy/2)))
// return true;
m_pkChar->SetNowWalking(true);
//if (m_pkChar->Goto(m_pkChar->GetX() + (int) fx, m_pkChar->GetY() + (int) fy))
// m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
if (!m_pkChar->IsStateMove() && m_pkChar->Goto(dest_x, dest_y))
m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
m_dwLastActionTime = get_dword_time();
return true;
}
// char_state.cpp StateHorse<73>Լ<EFBFBD> <20>׳<EFBFBD> C&P -_-;
bool CPetActor::_UpdateFollowAI()
{
if (0 == m_pkChar->m_pkMobData)
{
//sys_err("[CPetActor::_UpdateFollowAI] m_pkChar->m_pkMobData is NULL");
return false;
}
// NOTE: ij<><C4B3><EFBFBD><EFBFBD>(<28><>)<29><> <20><><EFBFBD><EFBFBD> <20>̵<EFBFBD> <20>ӵ<EFBFBD><D3B5><EFBFBD> <20>˾ƾ<CBBE> <20>ϴµ<CFB4>, <20>ش<EFBFBD> <20><>(m_pkChar->m_pkMobData->m_table.sMovingSpeed)<29><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> <20>˾Ƴ<CBBE> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// m_pkChar->m_pkMobData <20><><EFBFBD><EFBFBD> invalid<69><64> <20><><EFBFBD><20><><EFBFBD><EFBFBD> <20>߻<EFBFBD><DFBB><EFBFBD>. <20><><EFBFBD><EFBFBD> <20>ð<EFBFBD><C3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ľ<EFBFBD><C4BE>ϰ<EFBFBD> <20>ϴ<EFBFBD><CFB4><EFBFBD> m_pkChar->m_pkMobData <20><><EFBFBD><EFBFBD> <20>ƿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʵ<EFBFBD><CAB5><EFBFBD> <20><>.
// <20><><EFBFBD><20>Ź<EFBFBD> <20>˻<EFBFBD><CBBB>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʱ<EFBFBD>ȭ <20><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD>.. -_-;; <20>ФФФФФФФФ<D0A4>
if (0 == m_originalMoveSpeed)
{
const CMob* mobData = CMobManager::Instance().Get(m_dwVnum);
if (0 != mobData)
m_originalMoveSpeed = mobData->m_table.sMovingSpeed;
}
float START_FOLLOW_DISTANCE = 300.0f; // <20><> <20>Ÿ<EFBFBD> <20>̻<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѿư<D1BE><C6B0><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float START_RUN_DISTANCE = 900.0f; // <20><> <20>Ÿ<EFBFBD> <20>̻<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>پ <20>Ѿư<D1BE>.
float RESPAWN_DISTANCE = 4500.f; // <20><> <20>Ÿ<EFBFBD> <20>̻<EFBFBD> <20>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF>.
int APPROACH = 200; // <20><><EFBFBD><EFBFBD> <20>Ÿ<EFBFBD>
bool bDoMoveAlone = true; // ij<><C4B3><EFBFBD>Ϳ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> ȥ<><C8A5> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD><CFB0><EFBFBD> <20><><EFBFBD><EFBFBD> -_-;
bool bRun = false; // <20>پ<EFBFBD><D9BE><EFBFBD> <20>ϳ<EFBFBD>?
DWORD currentTime = get_dword_time();
long ownerX = m_pkOwner->GetX(); long ownerY = m_pkOwner->GetY();
long charX = m_pkChar->GetX(); long charY = m_pkChar->GetY();
float fDist = DISTANCE_APPROX(charX - ownerX, charY - ownerY);
if (fDist >= RESPAWN_DISTANCE)
{
float fOwnerRot = m_pkOwner->GetRotation() * 3.141592f / 180.f;
float fx = -APPROACH * cos(fOwnerRot);
float fy = -APPROACH * sin(fOwnerRot);
if (m_pkChar->Show(m_pkOwner->GetMapIndex(), ownerX + fx, ownerY + fy))
{
return true;
}
}
if (fDist >= START_FOLLOW_DISTANCE)
{
if( fDist >= START_RUN_DISTANCE)
{
bRun = true;
}
m_pkChar->SetNowWalking(!bRun); // NOTE: <20>Լ<EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ߴ°<DFB4><C2B0><EFBFBD> <20>˾Ҵµ<D2B4> SetNowWalking(false) <20>ϸ<EFBFBD> <20>ٴ°<D9B4><C2B0><EFBFBD>.. -_-;
Follow(APPROACH);
m_pkChar->SetLastAttacked(currentTime);
m_dwLastActionTime = currentTime;
}
//else
//{
// if (fabs(m_pkChar->GetRotation() - GetDegreeFromPositionXY(charX, charY, ownerX, ownerX)) > 10.f || fabs(m_pkChar->GetRotation() - GetDegreeFromPositionXY(charX, charY, ownerX, ownerX)) < 350.f)
// {
// m_pkChar->Follow(m_pkOwner, APPROACH);
// m_pkChar->SetLastAttacked(currentTime);
// m_dwLastActionTime = currentTime;
// }
//}
// Follow <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ΰ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ÿ<EFBFBD> <20>̳<EFBFBD><CCB3><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٸ<EFBFBD> <20><><EFBFBD><EFBFBD>
else
m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
//else if (currentTime - m_dwLastActionTime > number(5000, 12000))
//{
// this->_UpdatAloneActionAI(START_FOLLOW_DISTANCE / 2, START_FOLLOW_DISTANCE);
//}
return true;
}
bool CPetActor::Update(DWORD deltaTime)
{
bool bResult = true;
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>׾<EFBFBD><D7BE>ų<EFBFBD>, <20><>ȯ<EFBFBD><C8AF> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>°<EFBFBD> <20>̻<EFBFBD><CCBB>ϴٸ<CFB4> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. (NOTE: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>̷<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF> <20><><EFBFBD><EFBFBD> DEAD <20><><EFBFBD>¿<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD>-_-;)
// <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ų<EFBFBD>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>°<EFBFBD> <20>ƴ϶<C6B4><CFB6><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
if (m_pkOwner->IsDead() || (IsSummoned() && m_pkChar->IsDead())
|| NULL == ITEM_MANAGER::instance().FindByVID(this->GetSummonItemVID())
|| ITEM_MANAGER::instance().FindByVID(this->GetSummonItemVID())->GetOwner() != this->GetOwner()
)
{
this->Unsummon();
return true;
}
if (this->IsSummoned() && HasOption(EPetOption_Followable))
bResult = bResult && this->_UpdateFollowAI();
return bResult;
}
//NOTE : <20><><EFBFBD><EFBFBD>!!! MinDistance<63><65> ũ<><C5A9> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŭ<EFBFBD><C5AD> <20><>ȭ<EFBFBD><C8AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> follow<6F><77><EFBFBD><EFBFBD> <20>ʴ´<CAB4>,
bool CPetActor::Follow(float fMinDistance)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> <20>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
if( !m_pkOwner || !m_pkChar)
return false;
float fOwnerX = m_pkOwner->GetX();
float fOwnerY = m_pkOwner->GetY();
float fPetX = m_pkChar->GetX();
float fPetY = m_pkChar->GetY();
float fDist = DISTANCE_SQRT(fOwnerX - fPetX, fOwnerY - fPetY);
if (fDist <= fMinDistance)
return false;
m_pkChar->SetRotationToXY(fOwnerX, fOwnerY);
float fx, fy;
float fDistToGo = fDist - fMinDistance;
GetDeltaByDegree(m_pkChar->GetRotation(), fDistToGo, &fx, &fy);
if (!m_pkChar->Goto((int)(fPetX+fx+0.5f), (int)(fPetY+fy+0.5f)) )
return false;
m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0, 0);
return true;
}
void CPetActor::SetSummonItem (LPITEM pItem)
{
if (NULL == pItem)
{
m_dwSummonItemVID = 0;
m_dwSummonItemVnum = 0;
return;
}
m_dwSummonItemVID = pItem->GetVID();
m_dwSummonItemVnum = pItem->GetVnum();
}
void CPetActor::GiveBuff()
{
// <20><>Ȳ <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߻<EFBFBD><DFBB><EFBFBD>.
if (34004 == m_dwVnum || 34009 == m_dwVnum)
{
if (NULL == m_pkOwner->GetDungeon())
{
return;
}
}
LPITEM item = ITEM_MANAGER::instance().FindByVID(m_dwSummonItemVID);
if (NULL != item)
item->ModifyPoints(true);
return ;
}
void CPetActor::ClearBuff()
{
if (NULL == m_pkOwner)
return ;
TItemTable* item_proto = ITEM_MANAGER::instance().GetTable(m_dwSummonItemVnum);
if (NULL == item_proto)
return;
for (int i = 0; i < ITEM_APPLY_MAX_NUM; i++)
{
if (item_proto->aApplies[i].bType == APPLY_NONE)
continue;
m_pkOwner->ApplyPoint(item_proto->aApplies[i].bType, -item_proto->aApplies[i].lValue);
}
return ;
}
///////////////////////////////////////////////////////////////////////////////////////
// CPetSystem
///////////////////////////////////////////////////////////////////////////////////////
CPetSystem::CPetSystem(LPCHARACTER owner)
{
// assert(0 != owner && "[CPetSystem::CPetSystem] Invalid owner");
m_pkOwner = owner;
m_dwUpdatePeriod = 400;
m_dwLastUpdateTime = 0;
}
CPetSystem::~CPetSystem()
{
Destroy();
}
void CPetSystem::Destroy()
{
for (TPetActorMap::iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
{
CPetActor* petActor = iter->second;
if (0 != petActor)
{
delete petActor;
}
}
event_cancel(&m_pkPetSystemUpdateEvent);
m_petActorMap.clear();
}
/// <20><> <20>ý<EFBFBD><C3BD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ. <20><><EFBFBD>ϵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> AI ó<><C3B3> <20><><EFBFBD><EFBFBD> <20><>.
bool CPetSystem::Update(DWORD deltaTime)
{
bool bResult = true;
DWORD currentTime = get_dword_time();
// CHARACTER_MANAGER<45><52><EFBFBD><EFBFBD> ij<><C4B3><EFBFBD>ͷ<EFBFBD> Update<74><65> <20><> <20>Ű<EFBFBD><C5B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD> (Pulse<73><65><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD><C7BE>ִ<EFBFBD>)<29><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ӱ<EFBFBD><D3B0><EFBFBD> <20>ð<EFBFBD><C3B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>˾Ҵµ<D2B4>
// <20><><EFBFBD><EFBFBD> <20>ٸ<EFBFBD> <20><><EFBFBD>̶<EFBFBD><CCB6><EFBFBD>-_-; <20><><EFBFBD><20>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> deltaTime<6D><65> <20>ǹ̰<C7B9> <20><><EFBFBD><EFBFBD><EFBFBD>Ф<EFBFBD>
if (m_dwUpdatePeriod > currentTime - m_dwLastUpdateTime)
return true;
std::vector <CPetActor*> v_garbageActor;
for (TPetActorMap::iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
{
CPetActor* petActor = iter->second;
if (0 != petActor && petActor->IsSummoned())
{
LPCHARACTER pPet = petActor->GetCharacter();
if (NULL == CHARACTER_MANAGER::instance().Find(pPet->GetVID()))
{
v_garbageActor.push_back(petActor);
}
else
{
bResult = bResult && petActor->Update(deltaTime);
}
}
}
for (std::vector<CPetActor*>::iterator it = v_garbageActor.begin(); it != v_garbageActor.end(); it++)
DeletePet(*it);
m_dwLastUpdateTime = currentTime;
return bResult;
}
/// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
void CPetSystem::DeletePet(DWORD mobVnum)
{
TPetActorMap::iterator iter = m_petActorMap.find(mobVnum);
if (m_petActorMap.end() == iter)
{
sys_err("[CPetSystem::DeletePet] Can't find pet on my list (VNUM: %d)", mobVnum);
return;
}
CPetActor* petActor = iter->second;
if (0 == petActor)
sys_err("[CPetSystem::DeletePet] Null Pointer (petActor)");
else
delete petActor;
m_petActorMap.erase(iter);
}
/// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
void CPetSystem::DeletePet(CPetActor* petActor)
{
for (TPetActorMap::iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
{
if (iter->second == petActor)
{
delete petActor;
m_petActorMap.erase(iter);
return;
}
}
sys_err("[CPetSystem::DeletePet] Can't find petActor(0x%x) on my list(size: %d) ", petActor, m_petActorMap.size());
}
void CPetSystem::Unsummon(DWORD vnum, bool bDeleteFromList)
{
CPetActor* actor = this->GetByVnum(vnum);
if (0 == actor)
{
sys_err("[CPetSystem::GetByVnum(%d)] Null Pointer (petActor)", vnum);
return;
}
actor->Unsummon();
if (true == bDeleteFromList)
this->DeletePet(actor);
bool bActive = false;
for (TPetActorMap::iterator it = m_petActorMap.begin(); it != m_petActorMap.end(); it++)
{
bActive |= it->second->IsSummoned();
}
if (false == bActive)
{
event_cancel(&m_pkPetSystemUpdateEvent);
m_pkPetSystemUpdateEvent = NULL;
}
}
CPetActor* CPetSystem::Summon(DWORD mobVnum, LPITEM pSummonItem, const char* petName, bool bSpawnFar, DWORD options)
{
CPetActor* petActor = this->GetByVnum(mobVnum);
// <20><><EFBFBD>ϵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ƴ϶<C6B4><CFB6><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
if (0 == petActor)
{
petActor = M2_NEW CPetActor(m_pkOwner, mobVnum, options);
m_petActorMap.insert(std::make_pair(mobVnum, petActor));
}
DWORD petVID = petActor->Summon(petName, pSummonItem, bSpawnFar);
if (NULL == m_pkPetSystemUpdateEvent)
{
petsystem_event_info* info = AllocEventInfo<petsystem_event_info>();
info->pPetSystem = this;
m_pkPetSystemUpdateEvent = event_create(petsystem_update_event, info, PASSES_PER_SEC(1) / 4); // 0.25<EFBFBD><EFBFBD>
}
return petActor;
}
CPetActor* CPetSystem::GetByVID(DWORD vid) const
{
CPetActor* petActor = 0;
bool bFound = false;
for (TPetActorMap::const_iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
{
petActor = iter->second;
if (0 == petActor)
{
sys_err("[CPetSystem::GetByVID(%d)] Null Pointer (petActor)", vid);
continue;
}
bFound = petActor->GetVID() == vid;
if (true == bFound)
break;
}
return bFound ? petActor : 0;
}
/// <20><><EFBFBD><EFBFBD> <20><> <20><> <20>߿<EFBFBD><DFBF><EFBFBD> <20>־<EFBFBD><D6BE><EFBFBD> <20><> VNUM<55><4D> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>͸<EFBFBD> <20><>ȯ<EFBFBD>ϴ<EFBFBD> <20>Լ<EFBFBD>.
CPetActor* CPetSystem::GetByVnum(DWORD vnum) const
{
CPetActor* petActor = 0;
TPetActorMap::const_iterator iter = m_petActorMap.find(vnum);
if (m_petActorMap.end() != iter)
petActor = iter->second;
return petActor;
}
size_t CPetSystem::CountSummoned() const
{
size_t count = 0;
for (TPetActorMap::const_iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
{
CPetActor* petActor = iter->second;
if (0 != petActor)
{
if (petActor->IsSummoned())
++count;
}
}
return count;
}
void CPetSystem::RefreshBuff()
{
for (TPetActorMap::const_iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
{
CPetActor* petActor = iter->second;
if (0 != petActor)
{
if (petActor->IsSummoned())
{
petActor->GiveBuff();
}
}
}
}

163
game/src/PetSystem.h Normal file
View File

@ -0,0 +1,163 @@
#ifndef __HEADER_PET_SYSTEM__
#define __HEADER_PET_SYSTEM__
class CHARACTER;
// TODO: <20><><EFBFBD><EFBFBD><EFBFBD>μ<EFBFBD><CEBC><EFBFBD> <20>ɷ<EFBFBD>ġ? <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ģ<>е<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>Ÿ<EFBFBD><C5B8><EFBFBD><EFBFBD>... <20><>ġ
struct SPetAbility
{
};
/**
*/
class CPetActor //: public CHARACTER
{
public:
enum EPetOptions
{
EPetOption_Followable = 1 << 0,
EPetOption_Mountable = 1 << 1,
EPetOption_Summonable = 1 << 2,
EPetOption_Combatable = 1 << 3,
};
protected:
friend class CPetSystem;
CPetActor(LPCHARACTER owner, DWORD vnum, DWORD options = EPetOption_Followable | EPetOption_Summonable);
// CPetActor(LPCHARACTER owner, DWORD vnum, const SPetAbility& petAbility, DWORD options = EPetOption_Followable | EPetOption_Summonable);
virtual ~CPetActor();
virtual bool Update(DWORD deltaTime);
protected:
virtual bool _UpdateFollowAI(); ///< <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ٴϴ<D9B4> AI ó<><C3B3>
virtual bool _UpdatAloneActionAI(float fMinDist, float fMaxDist); ///< <20><><EFBFBD><EFBFBD> <20><>ó<EFBFBD><C3B3><EFBFBD><EFBFBD> ȥ<><C8A5> <20><><EFBFBD><EFBFBD> AI ó<><C3B3>
/// @TODO
//virtual bool _UpdateCombatAI();
private:
bool Follow(float fMinDistance = 50.f);
public:
LPCHARACTER GetCharacter() const { return m_pkChar; }
LPCHARACTER GetOwner() const { return m_pkOwner; }
DWORD GetVID() const { return m_dwVID; }
DWORD GetVnum() const { return m_dwVnum; }
bool HasOption(EPetOptions option) const { return m_dwOptions & option; }
void SetName(const char* petName);
bool Mount();
void Unmount();
DWORD Summon(const char* petName, LPITEM pSummonItem, bool bSpawnFar = false);
void Unsummon();
bool IsSummoned() const { return 0 != m_pkChar; }
void SetSummonItem (LPITEM pItem);
DWORD GetSummonItemVID () { return m_dwSummonItemVID; }
// <20><><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20>Լ<EFBFBD><D4BC><EFBFBD> <20>ŵδ<C5B5> <20>Լ<EFBFBD>.
// <20>̰<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>Ѱ<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,
// POINT_MOV_SPEED, POINT_ATT_SPEED, POINT_CAST_SPEED<45><44> PointChange()<29><> <20>Լ<EFBFBD><D4BC><EFBFBD> <20><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ҿ<EFBFBD><D2BF><EFBFBD> <20><><EFBFBD>°<EFBFBD>,
// PointChange() <20><><EFBFBD>Ŀ<EFBFBD> <20><><EFBFBD>𼱰<EFBFBD> ComputePoints()<29><> <20>ϸ<EFBFBD> <20>ϴ<EFBFBD> <20>ʱ<EFBFBD>ȭ<EFBFBD>ǰ<EFBFBD>,
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, ComputePoints()<29><> <20>θ<EFBFBD><CEB8><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ŭ<><C5AC><EFBFBD><EFBFBD> POINT<4E><54> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ´ٴ<C2B4> <20>Ŵ<EFBFBD>.
// <20>׷<EFBFBD><D7B7><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD> ComputePoints() <20><><EFBFBD>ο<EFBFBD><CEBF><EFBFBD> petsystem->RefreshBuff()<29><> <20>θ<EFBFBD><CEB8><EFBFBD><EFBFBD><EFBFBD> <20>Ͽ<EFBFBD><CFBF><EFBFBD>,
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ClearBuff()<29><> <20>θ<EFBFBD><CEB8><EFBFBD>, ComputePoints<74><73> <20>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
void GiveBuff();
void ClearBuff();
private:
DWORD m_dwVnum;
DWORD m_dwVID;
DWORD m_dwOptions;
DWORD m_dwLastActionTime;
DWORD m_dwSummonItemVID;
DWORD m_dwSummonItemVnum;
short m_originalMoveSpeed;
std::string m_name;
LPCHARACTER m_pkChar; // Instance of pet(CHARACTER)
LPCHARACTER m_pkOwner;
// SPetAbility m_petAbility; // <20>ɷ<EFBFBD>ġ
};
/**
*/
class CPetSystem
{
public:
typedef boost::unordered_map<DWORD, CPetActor*> TPetActorMap; /// <VNUM, PetActor> map. (<28><> ij<><C4B3><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD> vnum<75><6D> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>..??)
public:
CPetSystem(LPCHARACTER owner);
virtual ~CPetSystem();
CPetActor* GetByVID(DWORD vid) const;
CPetActor* GetByVnum(DWORD vnum) const;
bool Update(DWORD deltaTime);
void Destroy();
size_t CountSummoned() const; ///< <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF>(<28><>üȭ <20><> ij<><C4B3><EFBFBD>Ͱ<EFBFBD> <20>ִ<EFBFBD>) <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
public:
void SetUpdatePeriod(DWORD ms);
CPetActor* Summon(DWORD mobVnum, LPITEM pSummonItem, const char* petName, bool bSpawnFar, DWORD options = CPetActor::EPetOption_Followable | CPetActor::EPetOption_Summonable);
void Unsummon(DWORD mobVnum, bool bDeleteFromList = false);
void Unsummon(CPetActor* petActor, bool bDeleteFromList = false);
// TODO: <20><>¥ <20><> <20>ý<EFBFBD><C3BD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><20><> <20><><EFBFBD><EFBFBD>. (ij<><C4B3><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߰<EFBFBD><DFB0><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...)
CPetActor* AddPet(DWORD mobVnum, const char* petName, const SPetAbility& ability, DWORD options = CPetActor::EPetOption_Followable | CPetActor::EPetOption_Summonable | CPetActor::EPetOption_Combatable);
void DeletePet(DWORD mobVnum);
void DeletePet(CPetActor* petActor);
void RefreshBuff();
private:
TPetActorMap m_petActorMap;
LPCHARACTER m_pkOwner; ///< <20><> <20>ý<EFBFBD><C3BD><EFBFBD><EFBFBD><EFBFBD> Owner
DWORD m_dwUpdatePeriod; ///< <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ <20>ֱ<EFBFBD> (ms<6D><73><EFBFBD><EFBFBD>)
DWORD m_dwLastUpdateTime;
LPEVENT m_pkPetSystemUpdateEvent;
};
/**
// Summon Pet
CPetSystem* petSystem = mainChar->GetPetSystem();
CPetActor* petActor = petSystem->Summon(~~~);
DWORD petVID = petActor->GetVID();
if (0 == petActor)
{
ERROR_LOG(...)
};
// Unsummon Pet
petSystem->Unsummon(petVID);
// Mount Pet
petActor->Mount()..
CPetActor::Update(...)
{
// AI : Follow, actions, etc...
}
*/
#endif //__HEADER_PET_SYSTEM__

399
game/src/SpeedServer.cpp Normal file
View File

@ -0,0 +1,399 @@
#include "stdafx.h"
#include <time.h>
#include "SpeedServer.h"
#include "locale_service.h"
// <20><20><><EFBFBD><EFBFBD> <20><><EFBFBD>ʽ<EFBFBD> <20><><EFBFBD><EFBFBD>ġ <20>ý<EFBFBD><C3BD><EFBFBD>
// by rtsummit
CSpeedServerManager::CSpeedServerManager()
{
}
CSpeedServerManager::~CSpeedServerManager()
{
}
CSpeedServerEmpireExp::CSpeedServerEmpireExp()
{
}
CSpeedServerEmpireExp::~CSpeedServerEmpireExp()
{
}
bool CSpeedServerManager::Initialize()
{
for (int i = 1; i < EMPIRE_MAX_NUM; i++)
{
sys_log (0,"speed manager init");
if(!Empire[i].Initialize (i))
{
sys_err ("EMPIRE %d Exp Bonus Manager Init fail",i);
return false;
}
}
return true;
}
bool CSpeedServerEmpireExp::Initialize (BYTE e)
{
empire = e;
sys_log (0, "empire exp init %d", empire);
snprintf (file_name, sizeof(file_name), "%s/exp_bonus_table_%d.txt", LocaleService_GetBasePath().c_str(), empire);
for (int i = 1; i < 6; i++)
{
wday_exp_table[i].push_back (HME (18, 0, 50));
wday_exp_table[i].push_back (HME (24, 0, 100));
}
wday_exp_table[0].push_back (HME (18, 0, 100));
wday_exp_table[0].push_back (HME (24, 0, 150));
wday_exp_table[6].push_back (HME (18, 0, 100));
wday_exp_table[6].push_back (HME (24, 0, 150));
LoadExpTable();
return true;
}
bool CSpeedServerEmpireExp::LoadWdayExpTable(int wday, char *str)
{
std::list <HME> &lst = wday_exp_table[wday];
lst.clear();
char *p, *n;
const char *delim = " \t\r\n";
char *t;
char *h, *m, *e;
int hour, min, exp;
sys_log (0, "str %s", str);
strtok (str, delim);
p = strtok (NULL, ";");
n = strtok (NULL, ";");
while (p != NULL)
{
t = strtok (p, delim);
e = strtok (NULL, delim);
h = strtok (t, ":");
m = strtok (NULL, delim);
if (!str_to_number (hour, h) || !str_to_number (min, m) || !str_to_number (exp, e))
{
sys_log (0, "h m e : %s %s %s",h, m, e);
sys_err ("Invalid argument. Please insert hh:mm exp");
return false;
}
sys_log (0, "h m e : %s %s %s",h, m, e);
lst.push_back (HME (hour, min, exp));
p = strtok (n, ";");
n = strtok (NULL, ";");
}
return true;
}
bool CSpeedServerManager::WriteExpTableOfEmpire(BYTE empire)
{
return Empire[empire].WriteExpTable();
}
bool CSpeedServerEmpireExp::WriteExpTable()
{
FILE *fp;
sys_log (0, "write");
if (0==file_name || 0==file_name[0])
return false;
if ((fp = fopen(file_name, "w"))==0)
{
return false;
}
char wday_name[7][4] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
for (int i = 0; i < 7; i++)
{
fprintf (fp, "%s", wday_name[i]);
for (std::list <HME>::iterator it = wday_exp_table[i].begin(); it != wday_exp_table[i].end(); it++)
{
fprintf (fp, " %d:%d %d;", it->hour, it->min, it->exp);
}
fprintf(fp, "\n");
}
for (std::map <Date, std::list <HME> >::iterator holi_it = holiday_map.begin(); holi_it != holiday_map.end(); holi_it++)
{
fprintf (fp, "HOLIDAY %d.%d.%d", holi_it->first.year + 1900, holi_it->first.mon + 1, holi_it->first.day);
for (std::list <HME>::iterator it = holi_it->second.begin(); it != holi_it->second.end(); it++)
{
fprintf (fp, " %d:%d %d;", it->hour, it->min, it->exp);
}
fprintf(fp, "\n");
}
fclose (fp);
return true;
}
bool CSpeedServerEmpireExp::LoadExpTable()
{
FILE *fp;
char one_line[256];
char temp[256];
const char *delim = " \t\r\n";
sys_log (0, "load");
if (0==file_name || 0==file_name[0])
return false;
if ((fp = fopen(file_name, "r"))==0)
return false;
while (fgets(one_line, 256, fp))
{
if (one_line[0]=='#')
continue;
strcpy(temp, one_line);
const char* token_string = strtok(one_line, delim);
if (NULL==token_string)
continue;
TOKEN("SUN")
{
LoadWdayExpTable (0, temp);
}
else TOKEN("MON")
{
LoadWdayExpTable (1, temp);
}
else TOKEN("TUE")
{
LoadWdayExpTable (2, temp);
}
else TOKEN("WED")
{
LoadWdayExpTable (3, temp);
}
else TOKEN("THU")
{
LoadWdayExpTable (4, temp);
}
else TOKEN("FRI")
{
LoadWdayExpTable (5, temp);
}
else TOKEN("SAT")
{
LoadWdayExpTable (6, temp);
}
else TOKEN("HOLIDAY")
{
std::list <HME> lst;
lst.clear();
char *p, *n;
char *t, *v;
char *h, *m, *e;
int hour, min, exp;
v = strtok (temp, delim);
v = strtok (NULL, delim);
sys_log (0, "holiday %s", v);
p = strtok (NULL, ";");
n = strtok (NULL, ";");
while (p != NULL)
{
t = strtok (p, delim);
e = strtok (NULL, delim);
h = strtok (t, ":");
m = strtok (NULL, delim);
if (!str_to_number (hour, h) || !str_to_number (min, m) || !str_to_number (exp, e))
{
sys_log (0, "h m e : %s %s %s",h, m, e);
sys_err ("Invalid argument. Please insert hh:mm exp");
return false;
}
sys_log (0, "h m e : %s %s %s",h, m, e);
lst.push_back (HME (hour, min, exp));
p = strtok (n, ";");
n = strtok (NULL, ";");
}
int year, mon, day;
if (!str_to_number (year, strtok (v, "."))
|| !str_to_number ( mon, strtok (NULL, "."))
|| !str_to_number ( day, strtok (NULL, ".")))
{
sys_err ("Invalid Date");
return false;
}
sys_log (0, "y m d %d %d %d",year, mon, day);
holiday_map.insert (std::pair <Date, std::list <HME> > (Date (year - 1900, mon - 1, day), lst));
}
}
fclose(fp);
return true;
}
std::list <HME>& CSpeedServerManager::GetWdayExpTableOfEmpire(BYTE empire, int wday)
{
return Empire[empire].GetWdayExpTable(wday);
}
std::list <HME>& CSpeedServerEmpireExp::GetWdayExpTable(int wday)
{
return wday_exp_table[wday];
}
void CSpeedServerManager::SetWdayExpTableOfEmpire (BYTE empire, int wday, HME hme)
{
Empire[empire].SetWdayExpTable (wday, hme);
}
void CSpeedServerEmpireExp::SetWdayExpTable (int wday, HME hme)
{
wday_exp_table[wday].push_back (hme);
WriteExpTable();
}
void CSpeedServerManager::InitWdayExpTableOfEmpire (BYTE empire, int wday)
{
if (empire > EMPIRE_MAX_NUM)
{
sys_err ("invalid empire");
return;
}
Empire[empire].InitWdayExpTable (wday);
}
void CSpeedServerEmpireExp::InitWdayExpTable(int wday)
{
wday_exp_table[wday].clear();
}
std::list <HME>& CSpeedServerManager::GetHolidayExpTableOfEmpire(BYTE empire, Date date, bool &is_exist)
{
return Empire[empire].GetHolidayExpTable(date, is_exist);
}
std::list <HME>& CSpeedServerEmpireExp::GetHolidayExpTable(Date date, bool &is_exist)
{
std::map <Date, std::list <HME> >::iterator it = holiday_map.find(date);
if (it != holiday_map.end())
{
is_exist = true;
return it->second;
}
else
{
is_exist = false;
sys_err ("Cannot find Holiday %d %d %d",date.year, date.mon, date.day);
}
return it->second;
}
void CSpeedServerManager::SetHolidayExpTableOfEmpire (BYTE empire, Date date, HME hme)
{
Empire[empire].SetHolidayExpTable (date, hme);
}
void CSpeedServerEmpireExp::SetHolidayExpTable (Date date, HME hme)
{
std::map <Date, std::list <HME> >::iterator it = holiday_map.find(date);
if (it != holiday_map.end())
{
it->second.push_back (hme);
}
WriteExpTable();
}
void CSpeedServerManager::InitHolidayExpTableOfEmpire (BYTE empire, Date date)
{
if (empire > EMPIRE_MAX_NUM)
{
sys_err ("invalid empire");
return;
}
Empire[empire].InitHolidayExpTable (date);
}
void CSpeedServerEmpireExp::InitHolidayExpTable(Date date)
{
sys_log (0, "init holiday");
std::map <Date, std::list <HME> >::iterator it = holiday_map.find(date);
if (it == holiday_map.end())
{
std::list <HME> lst;
holiday_map.insert (std::pair <Date, std::list <HME> > (date, lst));
}
else
{
it->second.clear();
}
}
HME CSpeedServerManager::GetCurrentExpPrivOfEmpire (BYTE empire, int &duration, bool &is_change)
{
return Empire[empire].GetCurrentExpPriv (duration, is_change);
}
HME CSpeedServerEmpireExp::GetCurrentExpPriv(int &duration, bool &is_change)
{
struct tm* datetime;
time_t t;
t = time(NULL);
datetime = localtime(&t);
Date date (datetime -> tm_year, datetime -> tm_mon,
datetime -> tm_mday);
std::map <Date, std::list <HME> >::iterator holi_it = holiday_map.find(date);
int total_sec = datetime->tm_hour * 3600 + datetime->tm_min * 60 + datetime->tm_sec;
HME hme;
// <20><><EFBFBD><EFBFBD> <20><>¥<EFBFBD><C2A5> holiday<61≯<EFBFBD> holiday bonus<75><73> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
if (holi_it != holiday_map.end())
{
for (std::list <HME>::iterator it = holi_it->second.begin();
it != wday_exp_table[datetime->tm_wday].end(); it++)
{
// <20><><EFBFBD><EFBFBD> <20>ð<EFBFBD><C3B0><EFBFBD> <20>ð<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ȿ<EFBFBD> <20><><EFBFBD>ԵǸ<D4B5>,
if (total_sec < (it->hour * 3600 + it->min * 60 ))
{
hme = *it;
break;
}
}
}
else
{
for (std::list <HME>::iterator it = wday_exp_table[datetime->tm_wday].begin();
it != wday_exp_table[datetime->tm_wday].end(); it++)
{
// <20><><EFBFBD><EFBFBD> <20>ð<EFBFBD><C3B0><EFBFBD> <20>ð<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ȿ<EFBFBD> <20><><EFBFBD>ԵǸ<D4B5>,
if (total_sec < (it->hour * 3600 + it->min * 60 ))
{
hme = *it;
break;
}
}
}
duration = hme.hour * 3600 + hme.min * 60 - total_sec;
is_change = !(hme == current_hme);
current_hme = hme;
return hme;
}

129
game/src/SpeedServer.h Normal file
View File

@ -0,0 +1,129 @@
#ifndef __INC_METIN_II_GAME_SPEEDSERVER_H__
#define __INC_METIN_II_GAME_SPEEDSERVER_H__
#include "../../common/length.h"
#include <list>
// castle.cpp <20><> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ͽ<EFBFBD><CFBF><EFBFBD>
#define EMPIRE_NONE 0 // <20>ƹ<EFBFBD><C6B9><EFBFBD><EFBFBD><EFBFBD> <20>ƴ<EFBFBD>
#define EMPIRE_RED 1 // <20>ż<EFBFBD>
#define EMPIRE_YELLOW 2 // õ<><C3B5>
#define EMPIRE_BLUE 3 // <20><><EFBFBD><EFBFBD>
class HME
{
public :
int hour;
int min;
int exp;
HME (int h=0, int m=0, int e=0){
hour = h; min = m;
exp = e;
}
HME& operator=(const HME &rhs)
{
hour = rhs.hour;
min = rhs.min;
exp = rhs.exp;
return *this;
}
bool operator==(const HME &rhs) const
{
return hour == rhs.hour
&& min == rhs.min
&& exp == rhs.exp;
}
bool operator<(const HME &rhs) const
{
return (hour<rhs.hour)
|| (hour==rhs.hour) && (min<rhs.min);
}
};
class Date
{
public :
int year;
int mon;
int day;
Date (int y = 0, int m = 0, int d = 0)
{
year = y; mon = m; day = d;
}
bool operator==(const Date &rhs) const
{
return year == rhs.year
&& mon == rhs.mon
&& day == rhs.day;
}
bool operator<(const Date &rhs) const
{
return (year<rhs.year)
|| (year==rhs.year) && (mon<rhs.mon)
|| (year==rhs.year) && (mon==rhs.mon) && (day<rhs.day);
}
};
class CSpeedServerEmpireExp
{
public :
CSpeedServerEmpireExp();
~CSpeedServerEmpireExp();
bool Initialize (BYTE empire);
std::list <HME>& GetWdayExpTable(int wday);
void SetWdayExpTable(int wday, HME hme);
std::list <HME>& GetHolidayExpTable(Date date, bool &is_exist);
void SetHolidayExpTable(Date date, HME hme);
void InitWdayExpTable(int wday);
void InitHolidayExpTable(Date date);
HME GetCurrentExpPriv (int &duration, bool &is_change);
bool WriteExpTable();
private :
bool LoadExpTable ();
bool LoadWdayExpTable (int wday, char *str);
BYTE empire;
char file_name [256];
HME current_hme;
std::map <Date, std::list <HME> > holiday_map;
std::list <HME> wday_exp_table[7];
};
class CSpeedServerManager : public singleton<CSpeedServerManager>
{
public:
CSpeedServerManager();
~CSpeedServerManager();
bool Initialize ();
std::list <HME>& GetWdayExpTableOfEmpire (BYTE empire, int wday);
void SetWdayExpTableOfEmpire (BYTE empire, int wday, HME hme);
void InitWdayExpTableOfEmpire (BYTE empire, int wday);
std::list <HME>& GetHolidayExpTableOfEmpire (BYTE empire, Date date, bool &is_exist);
void SetHolidayExpTableOfEmpire (BYTE empire, Date date, HME hme);
void InitHolidayExpTableOfEmpire (BYTE empire, Date date);
bool WriteExpTableOfEmpire (BYTE empire);
HME GetCurrentExpPrivOfEmpire (BYTE empire, int &duration, bool &is_change);
private:
CSpeedServerEmpireExp Empire[EMPIRE_MAX_NUM];
};
#endif

View File

@ -0,0 +1,92 @@
/**
*
* @file TrafficProfiler.cpp
* @brief TrafficProfiler class implementation file
* @author Bang2ni
* @version 05/07/07 Bang2ni - First release.
*
*/
#include "stdafx.h"
#include "TrafficProfiler.h"
TrafficProfiler::TrafficProfiler()
: m_pfProfileLogFile(NULL), m_dwFlushCycle(0), m_tmProfileStartTime(0), m_dwTotalTraffic(0), m_dwTotalPacket(0)
{
m_aTrafficVec[ 0 ].resize( 256 );
m_aTrafficVec[ 1 ].resize( 256 );
}
TrafficProfiler::~TrafficProfiler()
{
if ( m_pfProfileLogFile )
fclose( m_pfProfileLogFile );
}
bool TrafficProfiler::Initialize( DWORD dwFlushCycle, const char* pszFileName )
{
m_pfProfileLogFile = fopen( pszFileName, "w" );
if ( !m_pfProfileLogFile )
return false;
m_dwFlushCycle = dwFlushCycle;
InitializeProfiling();
return true;
}
bool TrafficProfiler::Flush()
{
if ( !m_pfProfileLogFile )
return false;
//
// Profling result write to file
//
fprintf( m_pfProfileLogFile, "# Profile Start: %s", ctime( &m_tmProfileStartTime ) );
fprintf( m_pfProfileLogFile, "Total traffic: %u bytes\n", m_dwTotalTraffic );
fprintf( m_pfProfileLogFile, "Total used packet: %u\n", m_dwTotalPacket );
fprintf( m_pfProfileLogFile, "------------------ Input ------------------\n" );
for ( int idx = 0; idx < (int)IODIR_MAX; idx++ )
{
fprintf( m_pfProfileLogFile, "Packet\tCount\tTotal Size\tAverage\n" );
BYTE byHeader = 0;
for ( TrafficVec::iterator it = m_aTrafficVec[ idx ].begin(); it != m_aTrafficVec[ idx ].end(); ++it, byHeader++ )
{
if ( it->second )
fprintf( m_pfProfileLogFile, "%d\t%u\t%u\t\t%u\n", byHeader, it->second, it->first, it->first / it->second );
}
fprintf( m_pfProfileLogFile, "------------------ Output -----------------\n" );
}
time_t cur = time( NULL );
fprintf( m_pfProfileLogFile, "# Profile End(Flush): %s", ctime( &cur ) );
fflush( m_pfProfileLogFile );
//
// Initialization
//
InitializeProfiling();
return true;
}
void TrafficProfiler::InitializeProfiling()
{
m_tmProfileStartTime = time( NULL );
m_dwTotalPacket = 0;
m_dwTotalTraffic = 0;
TrafficInfo empty( 0, 0 );
for ( int idx = 0; idx < (int)IODIR_MAX; idx++ )
{
for ( TrafficVec::iterator it = m_aTrafficVec[ idx ].begin(); it != m_aTrafficVec[ idx ].end(); ++it )
*it = empty;
}
}

115
game/src/TrafficProfiler.h Normal file
View File

@ -0,0 +1,115 @@
/**
*
* @file TrafficProfiler.h
* @brief TrafficProfiler class definition file
* @author Bang2ni
* @version 05/07/07 Bang2ni - First release.
*
*/
#ifndef _METIN_II_TRAFFICPROFILER_H_
#define _METIN_II_TRAFFICPROFILER_H_
/**
* @class TrafficProfiler
* @brief Network I/O traffic <20><> <20><>Ŷ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> profiler.
* @author Bang2ni
* @version 05/07/07 Bang2ni - First release.
*
* <20>ð<EFBFBD><C3B0><EFBFBD> <20><><EFBFBD><EFBFBD> Network I/O <20><> traffic <20><> <20><>Ŷ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD>, Text file <20><><EFBFBD>·<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ۼ<EFBFBD><DBBC>Ѵ<EFBFBD>.
*/
class TrafficProfiler : public singleton< TrafficProfiler >
{
public:
/// I/O <20><><EFBFBD><EFBFBD>
enum IODirection {
IODIR_INPUT = 0, ///< Input
IODIR_OUTPUT, ///< Output
IODIR_MAX
};
public:
/// Constructor
TrafficProfiler( void );
/// Destructor
~TrafficProfiler( void );
/// Profiling <20><> <20>ʿ<EFBFBD><CABF><EFBFBD> <20>ʱ<EFBFBD>ȭ<EFBFBD><C8AD> <20>Ѵ<EFBFBD>.
/**
* @param [in] dwFlushCycle Flush <20>ֱ<EFBFBD>. <20><> <20><><EFBFBD><EFBFBD><EFBFBD>̴<EFBFBD>.
* @param [in] pszLogFileName Profiling log file <20><> <20≯<EFBFBD>
* @return false <20><> <20><><EFBFBD><EFBFBD> profiling log file <20><> open <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ߴ<EFBFBD>.
*
* profiling log file <20><> open(<28><><EFBFBD><EFBFBD>) <20>Ѵ<EFBFBD>.
*/
bool Initialize( DWORD dwFlushCycle, const char* pszLogFileName );
/// Profiling <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>۵ưų<C6B0> <20><><EFBFBD><EFBFBD> <20><> Packet <20><> Report <20>Ѵ<EFBFBD>.
/**
* @param [in] dir Profiling <20><> Packet <20><> <20><><EFBFBD><EFBFBD>
* @param [in] byHeader Packet <20><><EFBFBD><EFBFBD>
* @param [in] dwSize Packet <20><> <20><> size
* @return Initialize <20><><EFBFBD><EFBFBD> <20>ʾҴٸ<D2B4> false <20><> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
*
* Packet <20><> <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> size <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ų<EFBFBD><C5B2>.
* Initialize <20><><EFBFBD>ij<EFBFBD> <20>ֱ<EFBFBD> Flush <20><> <20><><EFBFBD>Ŀ<EFBFBD> Flush <20>ֱ<EFBFBD> <20><>ŭ <20>ð<EFBFBD><C3B0><EFBFBD> <20><20><> ȣ<><C8A3><EFBFBD>ȴٸ<C8B4> Report <20><><EFBFBD><EFBFBD> Flush <20>Ѵ<EFBFBD>.
*/
bool Report( IODirection dir, BYTE byHeader, DWORD dwSize )
{
ComputeTraffic( dir, byHeader, dwSize );
if ( (DWORD)(time( NULL ) - m_tmProfileStartTime) >= m_dwFlushCycle )
return Flush();
return true;
}
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Report <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD>.
/**
* @return Initialize <20><><EFBFBD><EFBFBD> <20>ʾҴ<CABE>.
*/
bool Flush( void );
private:
/// Profling <20><> <20><><EFBFBD>õ<EFBFBD> variables <20><> <20>ʱ<EFBFBD>ȭ <20>Ѵ<EFBFBD>.
void InitializeProfiling( void );
/// Report <20><> Packet <20><> traffic <20><> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
/**
* @param [in] dir Profiling <20><> Packet <20><> <20><><EFBFBD><EFBFBD>
* @param [in] byHeader Packet <20><><EFBFBD><EFBFBD>
* @param [in] dwSize Packet <20><> <20><> size
*/
void ComputeTraffic( IODirection dir, BYTE byHeader, DWORD dwSize )
{
TrafficInfo& rTrafficInfo = m_aTrafficVec[ dir ][ byHeader ];
m_dwTotalTraffic += dwSize;
m_dwTotalPacket += !rTrafficInfo.second;
rTrafficInfo.first += dwSize;
rTrafficInfo.second++;
}
/// Traffic info type.
/**
* first: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> size
* second: <20><> packet <20><> <20><><EFBFBD>۵<EFBFBD> Ƚ<><C8BD>
*/
typedef std::pair< DWORD, DWORD > TrafficInfo;
/// Traffic info vector.
typedef std::vector< TrafficInfo > TrafficVec;
FILE* m_pfProfileLogFile; ///< Profile log file pointer
DWORD m_dwFlushCycle; ///< Flush <20>ֱ<EFBFBD>
time_t m_tmProfileStartTime; ///< <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ð<EFBFBD>. Flush <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Update <20>ȴ<EFBFBD>.
DWORD m_dwTotalTraffic; ///< Report <20><> <20><> Traffic <20>
DWORD m_dwTotalPacket; ///< Report <20><> <20><> Packet <20><>
TrafficVec m_aTrafficVec[ IODIR_MAX ]; ///< Report <20><> Traffic <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> vector<6F><72> <20>迭. <20><> <20><><EFBFBD><EFBFBD><E2B8B6> vector <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
};
#endif // _METIN_II_TRAFFICPROFILER_H_

329
game/src/XTrapManager.cpp Normal file
View File

@ -0,0 +1,329 @@
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#if defined(_WIN32) || defined(WIN32) || defined(_WIN64) || defined(WIN64)
#include <io.h>
#include <windows.h>
#include <tchar.h>
#else
#include <dlfcn.h>
#include <unistd.h>
#endif
#include <XTrap_S_Interface.h>
#include "char.h"
#include "config.h"
#include "event.h"
#include "log.h"
#include "desc.h"
#include "packet.h"
#include "XTrapManager.h"
#define CSFILE_NUM 2
#define XTRAP_CS1_CHECK_CYCLE PASSES_PER_SEC(20) // per 20sec
unsigned char g_XTrap_ClientMap[CSFILE_NUM][XTRAP_CS4_BUFSIZE_MAP];
struct CXTrapManager::sXTrapContext
{
//API function pointers
PFN_XTrap_S_Start XTrap_S_Start;
PFN_XTrap_S_SessionInit XTrap_S_SessionInit;
PFN_XTrap_CS_Step1 XTrap_CS_Step1;
PFN_XTrap_CS_Step3 XTrap_CS_Step3;
PFN_XTrap_S_SetActiveCode XTrap_S_SetActiveCode;
PFN_XTrap_S_SetOption XTrap_S_SetOption;
PFN_XTrap_S_SetAllowDelay XTrap_S_SetAllowDelay;
PFN_XTrap_S_SendGamePacket XTrap_S_SendGamePacket;
PFN_XTrap_S_RecvGamePacket XTrap_S_RecvGamePacket;
//handle
void* hXTrap4Server;
};
CXTrapManager::CXTrapManager()
{
m_pImpl = M2_NEW sXTrapContext;
memset( m_pImpl, 0x00, sizeof(sXTrapContext) );
}
CXTrapManager::~CXTrapManager()
{
#ifdef __FreeBSD__
if (m_pImpl->hXTrap4Server)
{
dlclose(m_pImpl->hXTrap4Server);
}
#endif
M2_DELETE(m_pImpl);
}
#ifdef __FreeBSD__
void CXTrapManager::MapReloadSignalHandler( int signal )
{
for(int i=0; i<CSFILE_NUM; ++i )
{
if( Instance().LoadClientMapFile(i) )
sys_log(0, "client map file(map%d).CS3 is reloaded", i+1 );
}
}
void CXTrapManager::NotifyMapFileChanged( const std::string& fileName, eFileUpdatedOptions eUpdateOption )
{
MapReloadSignalHandler(1);
}
#endif
bool CXTrapManager::LoadXTrapModule()
{
#ifdef __FreeBSD__
//first load client mapfile
bool bClientMapFileLoaded = false;
for(int i=0; i<CSFILE_NUM; ++i )
{
if( LoadClientMapFile(i) )
{
bClientMapFileLoaded = true;
}
}
if( !bClientMapFileLoaded )
{
sys_err("XTrap-failed to load at least one client map file. map file name should be map1.CS3 or map2.CS3");
return false;
}
//load shared objects
char sDllBinFile[] ="./libXTrap4Server.so";
m_pImpl->hXTrap4Server = dlopen(sDllBinFile, RTLD_LAZY);
if (m_pImpl->hXTrap4Server == 0)
{
sys_err("XTrap-failed to load so reason:%s", dlerror()) ;
return false;
}
void* hXTrapHandle = m_pImpl->hXTrap4Server;
m_pImpl->XTrap_S_Start = (PFN_XTrap_S_Start) dlsym(hXTrapHandle, "XTrap_S_Start");
m_pImpl->XTrap_S_SessionInit = (PFN_XTrap_S_SessionInit) dlsym(hXTrapHandle, "XTrap_S_SessionInit");
m_pImpl->XTrap_CS_Step1 = (PFN_XTrap_CS_Step1) dlsym(hXTrapHandle, "XTrap_CS_Step1");
m_pImpl->XTrap_CS_Step3 = (PFN_XTrap_CS_Step3) dlsym(hXTrapHandle, "XTrap_CS_Step3");
m_pImpl->XTrap_S_SetActiveCode = (PFN_XTrap_S_SetActiveCode) dlsym(hXTrapHandle, "XTrap_S_SetActiveCode");
m_pImpl->XTrap_S_SetOption = (PFN_XTrap_S_SetOption) dlsym(hXTrapHandle, "XTrap_S_SetOption");
m_pImpl->XTrap_S_SetAllowDelay = (PFN_XTrap_S_SetAllowDelay) dlsym(hXTrapHandle, "XTrap_S_SetAllowDelay");
m_pImpl->XTrap_S_SendGamePacket = (PFN_XTrap_S_SendGamePacket) dlsym(hXTrapHandle, "XTrap_S_SendGamePacket");
m_pImpl->XTrap_S_RecvGamePacket = (PFN_XTrap_S_RecvGamePacket) dlsym(hXTrapHandle, "XTrap_S_RecvGamePacket");
if (m_pImpl->XTrap_S_Start == NULL ||
m_pImpl->XTrap_S_SessionInit == NULL ||
m_pImpl->XTrap_CS_Step1 == NULL ||
m_pImpl->XTrap_CS_Step3 == NULL ||
m_pImpl->XTrap_S_SetOption == NULL ||
m_pImpl->XTrap_S_SetAllowDelay == NULL ||
m_pImpl->XTrap_S_SendGamePacket == NULL ||
m_pImpl->XTrap_S_RecvGamePacket == NULL)
{
sys_err("XTrap-failed to load function ptrs");
return false;
}
//start server module
m_pImpl->XTrap_S_Start( 600, CSFILE_NUM, g_XTrap_ClientMap, NULL );
//NOTE : <20>ϴ<EFBFBD> XProtect<63><74><EFBFBD><20><><EFBFBD>װ<EFBFBD> <20>־ <20>ڵ念<DAB5><E5BFB5> üũ<C3BC><C5A9> <20><><EFBFBD><EFBFBD>.
m_pImpl->XTrap_S_SetActiveCode( XTRAP_ACTIVE_CODE_THEMIDA );
//setup signal
signal(SIGUSR2, CXTrapManager::MapReloadSignalHandler);
#endif
return true;
}
bool CXTrapManager::LoadClientMapFile( unsigned int iMapIndex )
{
#ifdef __FreeBSD__
//index check
if( iMapIndex >= CSFILE_NUM )
{
return false;
}
char szFileName[1024] = {0,};
snprintf(szFileName, sizeof(szFileName), "map%d.CS3", iMapIndex+1);
FILE* fi = 0;
fi = fopen(szFileName, "rb");
if (fi == NULL)
{
return false;
}
fread(g_XTrap_ClientMap[iMapIndex], XTRAP_CS4_BUFSIZE_MAP, 1, fi);
fclose(fi);
#endif
return true;
}
EVENTINFO(xtrap_cs1_check_info)
{
DynamicCharacterPtr ptrPC;
};
EVENTFUNC(xtrap_cs1_check_event)
{
xtrap_cs1_check_info* info = dynamic_cast<xtrap_cs1_check_info*>( event->info );
if ( info == NULL )
{
sys_err( "<xtrap_event> info null pointer" );
return 0;
}
TPacketXTrapCSVerify pack;
pack.bHeader = HEADER_GC_XTRAP_CS1_REQUEST;
bool bSuccess = CXTrapManager::instance().Verify_CSStep1( info->ptrPC, pack.bPacketData );
LPDESC lpClientDesc = info->ptrPC.Get()->GetDesc();
if( !lpClientDesc )
{
sys_err( "<xtrap_event> client session is invalid" );
return 0;
}
lpClientDesc->Packet( &pack, sizeof(pack) );
if( bSuccess )
{
return XTRAP_CS1_CHECK_CYCLE;
}
sys_err( "XTrap: hack is detected %s", lpClientDesc->GetHostName() );
info->ptrPC.Get()->Disconnect("XTrapCheckInvalid");
lpClientDesc->SetPhase(PHASE_CLOSE);
return 0;
}
bool CXTrapManager::CreateClientSession( LPCHARACTER lpCharSession )
{
if( !bXTrapEnabled )
return true;
if( !lpCharSession )
return false;
DWORD dwSessionID = lpCharSession->GetPlayerID();
ClientSessionMap::iterator it = m_mapClientSessions.find( dwSessionID );
if( it != m_mapClientSessions.end() )
{
sys_err("XTrap: client session is alreay registered");
return false;
}
//init session info
sSessionInfo infoData;
//xtrap session init
DWORD dwReturn = m_pImpl->XTrap_S_SessionInit( 600, CSFILE_NUM, g_XTrap_ClientMap, infoData.szSessionBuf );
if( dwReturn != 0 )
{
sys_err("XTrap: client session init failed");
}
xtrap_cs1_check_info* event_info = AllocEventInfo<xtrap_cs1_check_info>();
event_info->ptrPC = lpCharSession;
infoData.m_pCheckEvent = event_create(xtrap_cs1_check_event, event_info, XTRAP_CS1_CHECK_CYCLE);
m_mapClientSessions[dwSessionID] = infoData;
return true;
}
void CXTrapManager::DestroyClientSession( LPCHARACTER lpCharSession )
{
if( !bXTrapEnabled )
return;
if( !lpCharSession )
return;
DWORD dwSessionID = lpCharSession->GetPlayerID();
ClientSessionMap::iterator it = m_mapClientSessions.find( dwSessionID );
if( it == m_mapClientSessions.end() )
{
sys_err("XTrap: client session is already destroyed");
return;
}
event_cancel(&(it->second.m_pCheckEvent) );
m_mapClientSessions.erase(it);
}
bool CXTrapManager::Verify_CSStep1( LPCHARACTER lpCharSession, BYTE* pBufData )
{
if( !bXTrapEnabled )
return false;
if( !lpCharSession )
return false;
DWORD dwSessionID = lpCharSession->GetPlayerID();
ClientSessionMap::iterator it = m_mapClientSessions.find( dwSessionID );
if( it == m_mapClientSessions.end() )
{
sys_err("XTrap: client session is already destroyed");
return false;
}
int nReturn = m_pImpl->XTrap_CS_Step1( it->second.szSessionBuf, it->second.szPackBuf );
memcpy( pBufData, it->second.szPackBuf, VERIFY_PACK_LEN );
return (nReturn == 0) ? true : false;
}
void CXTrapManager::Verify_CSStep3( LPCHARACTER lpCharSession, BYTE* pBufData )
{
if( !bXTrapEnabled )
return;
if( !lpCharSession )
return;
DWORD dwSessionID = lpCharSession->GetPlayerID();
ClientSessionMap::iterator it = m_mapClientSessions.find( dwSessionID );
if( it == m_mapClientSessions.end() )
{
sys_log(0, "XTrap: client session is alreay destroyed");
return;
}
memcpy( it->second.szPackBuf, pBufData, VERIFY_PACK_LEN );
m_pImpl->XTrap_CS_Step3( it->second.szSessionBuf, it->second.szPackBuf );
//if( XTRAP_API_RETURN_DETECTHACK == m_pImpl->XTrap_CS_Step3( it->second.szSessionBuf, pBufData ) )
//{
// sys_error(0, "XTrap: client session is alreay destroyed");
//}
}

67
game/src/XTrapManager.h Normal file
View File

@ -0,0 +1,67 @@
#ifndef _XTRAP_MANAGER_H_
#define _XTRAP_MANAGER_H_
#include "IFileMonitor.h"
#define SESSION_BUF_LEN 320
#define VERIFY_PACK_LEN 128
#define SESSION_CSSTEP1_LEN 256
#pragma pack(1)
typedef struct PacketXTrapVerify
{
BYTE bHeader;
BYTE bPacketData[VERIFY_PACK_LEN];
} TPacketXTrapCSVerify;
#pragma pack()
class CXTrapManager : public singleton<CXTrapManager>
{
public:
CXTrapManager();
virtual ~CXTrapManager();
bool LoadXTrapModule();
bool LoadClientMapFile( unsigned int iMapIndex );
bool CreateClientSession( LPCHARACTER lpCharSession );
void DestroyClientSession( LPCHARACTER lpCharSession );
bool Verify_CSStep1( LPCHARACTER lpCharSession, BYTE* pOutBufData );
void Verify_CSStep3( LPCHARACTER lpCharSession, BYTE* pBufData );
#ifdef __FreeBSD__
static void MapReloadSignalHandler( int signal );
static void NotifyMapFileChanged( const std::string& fileName, eFileUpdatedOptions eUpdateOption );
#endif
private:
//pimpl`s idiom
struct sXTrapContext;
sXTrapContext* m_pImpl;
struct sSessionInfo
{
sSessionInfo()
{
m_pCheckEvent = NULL;
memset(szSessionBuf, 0x00, sizeof(szSessionBuf) );
memset(szPackBuf, 0x00, sizeof(szPackBuf) );
}
BYTE szSessionBuf[SESSION_BUF_LEN];
BYTE szPackBuf[VERIFY_PACK_LEN];
LPEVENT m_pCheckEvent;
};
typedef boost::unordered_map<DWORD, sSessionInfo> ClientSessionMap;
ClientSessionMap m_mapClientSessions;
};
#endif /* _XTRAP_MANAGER_H_ */

31
game/src/affect.cpp Normal file
View File

@ -0,0 +1,31 @@
#include "stdafx.h"
#ifndef DEBUG_ALLOC
#include <boost/pool/object_pool.hpp>
#endif
#include "affect.h"
#ifndef DEBUG_ALLOC
boost::object_pool<CAffect> affect_pool;
#endif
CAffect* CAffect::Acquire()
{
#ifndef DEBUG_ALLOC
return affect_pool.malloc();
#else
return M2_NEW CAffect;
#endif
}
void CAffect::Release(CAffect* p)
{
#ifndef DEBUG_ALLOC
affect_pool.free(p);
#else
M2_DELETE(p);
#endif
}

183
game/src/affect.h Normal file
View File

@ -0,0 +1,183 @@
#ifndef __INC_AFFECT_H
#define __INC_AFFECT_H
class CAffect
{
public:
DWORD dwType;
BYTE bApplyOn;
long lApplyValue;
DWORD dwFlag;
long lDuration;
long lSPCost;
static CAffect* Acquire();
static void Release(CAffect* p);
};
enum EAffectTypes
{
AFFECT_NONE,
AFFECT_MOV_SPEED = 200,
AFFECT_ATT_SPEED,
AFFECT_ATT_GRADE,
AFFECT_INVISIBILITY,
AFFECT_STR,
AFFECT_DEX, // 205
AFFECT_CON,
AFFECT_INT,
AFFECT_FISH_MIND_PILL,
AFFECT_POISON,
AFFECT_STUN, // 210
AFFECT_SLOW,
AFFECT_DUNGEON_READY,
AFFECT_DUNGEON_UNIQUE,
AFFECT_BUILDING,
AFFECT_REVIVE_INVISIBLE, // 215
AFFECT_FIRE,
AFFECT_CAST_SPEED,
AFFECT_HP_RECOVER_CONTINUE,
AFFECT_SP_RECOVER_CONTINUE,
AFFECT_POLYMORPH, // 220
AFFECT_MOUNT,
AFFECT_WAR_FLAG, // 222
AFFECT_BLOCK_CHAT, // 223
AFFECT_CHINA_FIREWORK,
AFFECT_BOW_DISTANCE, // 225
AFFECT_DEF_GRADE, // 226
AFFECT_PREMIUM_START = 500,
AFFECT_EXP_BONUS = 500, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
AFFECT_ITEM_BONUS = 501, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>
AFFECT_SAFEBOX = 502, // PREMIUM_SAFEBOX,
AFFECT_AUTOLOOT = 503, // PREMIUM_AUTOLOOT,
AFFECT_FISH_MIND = 504, // PREMIUM_FISH_MIND,
AFFECT_MARRIAGE_FAST = 505, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
AFFECT_GOLD_BONUS = 506, // <20><> <20><><EFBFBD><EFBFBD>Ȯ<EFBFBD><C8AE> 50%<25><><EFBFBD><EFBFBD>
AFFECT_PREMIUM_END = 509,
AFFECT_MALL = 510, // <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ
AFFECT_NO_DEATH_PENALTY = 511, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȣ (<28><><EFBFBD><EFBFBD>ġ<EFBFBD><C4A1> <20>г<EFBFBD>Ƽ<EFBFBD><C6BC> <20>ѹ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>)
AFFECT_SKILL_BOOK_BONUS = 512, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Ȯ<><C8AE><EFBFBD><EFBFBD> 50% <20><><EFBFBD><EFBFBD>)
AFFECT_SKILL_NO_BOOK_DELAY = 513, // <20>־ȼ<D6BE><C8BC><EFBFBD>
AFFECT_HAIR = 514, // <20><><EFBFBD><EFBFBD> ȿ<><C8BF>
AFFECT_COLLECT = 515, //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ
AFFECT_EXP_BONUS_EURO_FREE = 516, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> 14 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>⺻ ȿ<><C8BF>)
AFFECT_EXP_BONUS_EURO_FREE_UNDER_15 = 517,
AFFECT_UNIQUE_ABILITY = 518,
AFFECT_CUBE_1,
AFFECT_CUBE_2,
AFFECT_CUBE_3,
AFFECT_CUBE_4,
AFFECT_CUBE_5,
AFFECT_CUBE_6,
AFFECT_CUBE_7,
AFFECT_CUBE_8,
AFFECT_CUBE_9,
AFFECT_CUBE_10,
AFFECT_CUBE_11,
AFFECT_CUBE_12,
AFFECT_BLEND,
AFFECT_HORSE_NAME,
AFFECT_MOUNT_BONUS,
AFFECT_AUTO_HP_RECOVERY = 534,
AFFECT_AUTO_SP_RECOVERY = 535,
AFFECT_DRAGON_SOUL_QUALIFIED = 540,
AFFECT_DRAGON_SOUL_DECK_0 = 541,
AFFECT_DRAGON_SOUL_DECK_1 = 542,
AFFECT_RAMADAN_ABILITY = 300,
AFFECT_RAMADAN_RING = 301,
AFFECT_NOG_ABILITY = 302,
AFFECT_HOLLY_STONE_POWER = 303,
AFFECT_QUEST_START_IDX = 1000
};
enum EAffectBits
{
AFF_NONE,
AFF_YMIR,
AFF_INVISIBILITY,
AFF_SPAWN,
AFF_POISON,
AFF_SLOW,
AFF_STUN,
AFF_DUNGEON_READY, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>غ<EFBFBD> <20><><EFBFBD><EFBFBD>
AFF_DUNGEON_UNIQUE, // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ũ (Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD> <20>ø<EFBFBD><C3B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
AFF_BUILDING_CONSTRUCTION_SMALL,
AFF_BUILDING_CONSTRUCTION_LARGE,
AFF_BUILDING_UPGRADE,
AFF_MOV_SPEED_POTION,
AFF_ATT_SPEED_POTION,
AFF_FISH_MIND,
AFF_JEONGWIHON, // <20><><EFBFBD><EFBFBD>ȥ
AFF_GEOMGYEONG, // <20>˰<EFBFBD>
AFF_CHEONGEUN, // õ<><C3B5><EFBFBD><EFBFBD>
AFF_GYEONGGONG, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
AFF_EUNHYUNG, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
AFF_GWIGUM, // <20>Ͱ<EFBFBD>
AFF_TERROR, // <20><><EFBFBD><EFBFBD>
AFF_JUMAGAP, // <20>ָ<EFBFBD><D6B8><EFBFBD>
AFF_HOSIN, // ȣ<><C8A3>
AFF_BOHO, // <20><>ȣ
AFF_KWAESOK, // <20><><EFBFBD><EFBFBD>
AFF_MANASHIELD, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
AFF_MUYEONG, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> affect
AFF_REVIVE_INVISIBLE, // <20><>Ȱ<EFBFBD><C8B0> <20><><EFBFBD>õ<EFBFBD><C3B5><EFBFBD> <20><><EFBFBD><EFBFBD>
AFF_FIRE, // <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
AFF_GICHEON, // <20><>õ<EFBFBD><C3B5><EFBFBD><EFBFBD>
AFF_JEUNGRYEOK, // <20><><EFBFBD>¼<EFBFBD>
AFF_TANHWAN_DASH, // źȯ<C5BA>ݿ<EFBFBD> <20>޸<EFBFBD><DEB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ
AFF_PABEOP, // <20>Ĺ<EFBFBD><C4B9><EFBFBD>
AFF_CHEONGEUN_WITH_FALL, // õ<><C3B5><EFBFBD><EFBFBD>
AFF_POLYMORPH,
AFF_WAR_FLAG1,
AFF_WAR_FLAG2,
AFF_WAR_FLAG3,
AFF_CHINA_FIREWORK,
AFF_HAIR, // <20><><EFBFBD><EFBFBD>
AFF_GERMANY, // <20><><EFBFBD><EFBFBD>
AFF_BITS_MAX
};
extern void SendAffectAddPacket(LPDESC d, CAffect * pkAff);
// AFFECT_DURATION_BUG_FIX
enum AffectVariable
{
// Affect<63><74> <20><><EFBFBD>Ѵ<EFBFBD><D1B4><EFBFBD> <20><><EFBFBD><20>־<EFBFBD><D6BE><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
// <20>ð<EFBFBD><C3B0><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>̱<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ſ<EFBFBD> ū<><C5AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>Ѵ<20><><EFBFBD>ķ<EFBFBD><C4B7>̼<EFBFBD><CCBC><EFBFBD>.
//// 24<32><34>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD> 25<32><35>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD>.
// ... 25<32><35>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD>Ѵٰ<D1B4> <20>س<EFBFBD><D8B3><EFBFBD><EFBFBD><EFBFBD> 29bit <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20>ִ<EFBFBD> <20><>û<EFBFBD><C3BB> <20>ּ<EFBFBD><D6BC>̶<EFBFBD>...
// collect quest<73><74><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ð<EFBFBD><C3B0><EFBFBD> 60<36><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>, <20><><EFBFBD>⵵ 60<36><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
INFINITE_AFFECT_DURATION = 60 * 365 * 24 * 60 * 60
};
// END_AFFECT_DURATION_BUG_FIX
#endif

69
game/src/affect_flag.h Normal file
View File

@ -0,0 +1,69 @@
#ifndef __INC_METIN_II_AFFECT_FLAG_H__
#define __INC_METIN_II_AFFECT_FLAG_H__
#ifndef IS_SET
#define IS_SET(flag, bit) ((flag) & (bit))
#endif
#ifndef SET_BIT
#define SET_BIT(var, bit) ((var) |= (bit))
#endif
#ifndef REMOVE_BIT
#define REMOVE_BIT(var, bit) ((var) &= ~(bit))
#endif
#ifndef TOGGLE_BIT
#define TOGGLE_BIT(var, bit) ((var) = (var) ^ (bit))
#endif
struct TAffectFlag
{
DWORD bits[2];
inline TAffectFlag() { bits[0] = 0; bits[1] = 0; }
inline TAffectFlag(DWORD v1, DWORD v2 = 0) {bits[0] = v1; bits[1] = v2;}
inline bool IsSet(int flag) const
{
if (AFF_BITS_MAX <= flag || 0 >= flag)
return false;
return IS_SET(bits[(flag - 1) >> 5], (((DWORD)1) << ((flag - 1) & 31)));
}
inline void Set(int flag)
{
if (AFF_BITS_MAX <= flag || 0 >= flag)
return;
SET_BIT(bits[(flag-1)>>5], (((DWORD)1)<<((flag-1)&31)));
}
inline void Reset(int flag)
{
if (AFF_BITS_MAX <= flag || 0 >= flag)
return;
REMOVE_BIT(bits[(flag-1)>>5], (((DWORD)1)<<((flag-1)&31)));
}
inline TAffectFlag& operator = (const TAffectFlag& rhs)
{
bits[0] = rhs.bits[0];
bits[1] = rhs.bits[1];
return *this;
}
};
inline bool operator == (const TAffectFlag& lhs, const TAffectFlag& rhs)
{
return lhs.bits[0] == rhs.bits[0] && lhs.bits[1] == rhs.bits[1];
}
inline bool operator != (const TAffectFlag& lhs, const TAffectFlag& rhs)
{
return !(lhs == rhs);
}
#endif

371
game/src/ani.cpp Normal file
View File

@ -0,0 +1,371 @@
/*********************************************************************
* date : 2007.11.16
* file : ani.cpp
* author : mhh
* description :
*/
#define _ani_cpp_
#include "stdafx.h"
#include "char.h"
#include "item.h"
#include "ani.h"
#include "dev_log.h"
const char* FN_race_name(int race)
{
#define FN_NAME(race) case race: return #race
switch (race)
{
FN_NAME(MAIN_RACE_WARRIOR_M);
FN_NAME(MAIN_RACE_ASSASSIN_W);
FN_NAME(MAIN_RACE_SURA_M);
FN_NAME(MAIN_RACE_SHAMAN_W);
FN_NAME(MAIN_RACE_WARRIOR_W);
FN_NAME(MAIN_RACE_ASSASSIN_M);
FN_NAME(MAIN_RACE_SURA_W);
FN_NAME(MAIN_RACE_SHAMAN_M);
FN_NAME(MAIN_RACE_MAX_NUM);
}
return "UNKNOWN";
#undef FN_NAME
}
const char* FN_weapon_type(int weapon)
{
#define FN_NAME(weapon) case weapon: return #weapon
switch (weapon)
{
FN_NAME(WEAPON_SWORD);
FN_NAME(WEAPON_DAGGER);
FN_NAME(WEAPON_BOW);
FN_NAME(WEAPON_TWO_HANDED);
FN_NAME(WEAPON_BELL);
FN_NAME(WEAPON_FAN);
FN_NAME(WEAPON_ARROW);
FN_NAME(WEAPON_MOUNT_SPEAR);
FN_NAME(WEAPON_NUM_TYPES);
}
return "UNKNOWN";
#undef FN_NAME
}
class ANI
{
protected:
// [<5B><><EFBFBD><EFBFBD>][<5B>Ϲ<EFBFBD><30><C5BB>1][<5B><><EFBFBD><EFBFBD>][<5B>޺<EFBFBD>]
DWORD m_speed[MAIN_RACE_MAX_NUM][2][WEAPON_NUM_TYPES][9];
public:
ANI();
public:
bool load();
bool load_one_race(int race, const char *dir_name);
DWORD load_one_weapon(const char *dir_name, int weapon, BYTE combo, bool horse);
DWORD attack_speed(int race, int weapon, BYTE combo = 0, bool horse = false);
void print_attack_speed();
};
static class ANI s_ANI;
DWORD FN_attack_speed_from_file(const char *file)
{
FILE * fp = fopen(file, "r");
if (NULL == fp)
return 0;
int speed = 1000;
const char *key = "DirectInputTime";
const char *delim = " \t\r\n";
const char *field, *value;
char buf[1024];
while (fgets(buf, 1024, fp))
{
field = strtok(buf, delim);
value = strtok(NULL, delim);
if (field && value)
{
if (0 == strcasecmp(field, key))
{
float f_speed = strtof(value, NULL);
speed = (int) (f_speed * 1000.0);
break;
}
}
}
fclose(fp);
return speed;
}
ANI::ANI()
{
// set default value
for (int race = 0; race < MAIN_RACE_MAX_NUM; ++race)
{
for (int weapon = 0; weapon < WEAPON_NUM_TYPES; ++weapon)
{
for (BYTE combo = 0; combo <= 8; ++combo)
{
m_speed[race][0][weapon][combo] = 1000;
m_speed[race][1][weapon][combo] = 1000;
}
}
}
}
bool ANI::load()
{
const char* dir_name[MAIN_RACE_MAX_NUM] = {
"data/pc/warrior", // <20><><EFBFBD><EFBFBD>(<28><>)
"data/pc/assassin", // <20>ڰ<EFBFBD>(<28><>)
"data/pc/sura", // <20><><EFBFBD><EFBFBD>(<28><>)
"data/pc/shaman", // <20><><EFBFBD><EFBFBD>(<28><>)
"data/pc2/warrior", // <20><><EFBFBD><EFBFBD>(<28><>)
"data/pc2/assassin", // <20>ڰ<EFBFBD>(<28><>)
"data/pc2/sura", // <20><><EFBFBD><EFBFBD>(<28><>)
"data/pc2/shaman" // <20><><EFBFBD><EFBFBD>(<28><>)
};
for (int race = 0; race <MAIN_RACE_MAX_NUM; ++race)
{
if (false == load_one_race(race, dir_name[race]))
{
sys_err("ANI directory = %s", dir_name[race]);
return false;
}
}
return true;
}
DWORD ANI::load_one_weapon(const char *dir_name, int weapon, BYTE combo, bool horse)
{
char format[128];
char filename[256];
switch (weapon)
{
case WEAPON_SWORD:
strlcpy(format, "%s/%sonehand_sword/combo_%02d.msa", sizeof(format));
break;
case WEAPON_DAGGER:
strlcpy(format, "%s/%sdualhand_sword/combo_%02d.msa", sizeof(format));
break;
case WEAPON_BOW:
strlcpy(format, "%s/%sbow/attack.msa", sizeof(format));
break;
case WEAPON_TWO_HANDED:
strlcpy(format, "%s/%stwohand_sword/combo_%02d.msa", sizeof(format));
break;
case WEAPON_BELL:
strlcpy(format, "%s/%sbell/combo_%02d.msa", sizeof(format));
break;
case WEAPON_FAN:
strlcpy(format, "%s/%sfan/combo_%02d.msa", sizeof(format));
break;
default:
return 1000;
}
snprintf(filename, sizeof(filename), format, dir_name, horse ? "horse_" : "", combo);
DWORD speed = FN_attack_speed_from_file(filename);
if (speed == 0)
return 1000;
return speed;
}
bool ANI::load_one_race(int race, const char *dir_name)
{
if (NULL == dir_name || '\0' == dir_name[0])
return false;
for (int weapon = WEAPON_SWORD; weapon < WEAPON_NUM_TYPES; ++weapon)
{
dev_log(LOG_DEB0, "ANI (%s,%s)", FN_race_name(race), FN_weapon_type(weapon));
for (BYTE combo = 1; combo <= 8; ++combo)
{
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>
m_speed[race][0][weapon][combo] = load_one_weapon(dir_name, weapon, combo, false);
m_speed[race][0][weapon][0] = MIN(m_speed[race][0][weapon][0], m_speed[race][0][weapon][combo]); // <20>ּҰ<D6BC>
// <20><> <20><><EFBFBD><EFBFBD> <20><>
m_speed[race][1][weapon][combo] = load_one_weapon(dir_name, weapon, combo, true);
m_speed[race][1][weapon][0] = MIN(m_speed[race][1][weapon][0], m_speed[race][1][weapon][combo]); // <20>ּҰ<D6BC>
dev_log(LOG_DEB0, "combo%02d speed=%d horse=%d",
combo, m_speed[race][0][weapon][combo], m_speed[race][1][weapon][combo]);
}
dev_log(LOG_DEB0, "minspeed=%u", m_speed[race][0][weapon][0]);
}
return true;
}
DWORD ANI::attack_speed(int race, int weapon, BYTE combo, bool horse)
{
switch (race)
{
case MAIN_RACE_WARRIOR_M:
case MAIN_RACE_ASSASSIN_W:
case MAIN_RACE_SURA_M:
case MAIN_RACE_SHAMAN_W:
case MAIN_RACE_WARRIOR_W:
case MAIN_RACE_ASSASSIN_M:
case MAIN_RACE_SURA_W:
case MAIN_RACE_SHAMAN_M:
break;
default:
return 1000;
}
switch (weapon)
{
case WEAPON_SWORD:
case WEAPON_DAGGER:
case WEAPON_BOW:
case WEAPON_TWO_HANDED:
case WEAPON_BELL:
case WEAPON_FAN:
case WEAPON_ARROW:
case WEAPON_MOUNT_SPEAR:
break;
default:
return 1000;
}
return m_speed[race][horse ? 1 : 0][weapon][combo];
}
const char* FN_race_string(int race)
{
switch (race)
{
case MAIN_RACE_WARRIOR_M: return "WARRIOR_M";
case MAIN_RACE_ASSASSIN_W: return "ASSASSIN_W";
case MAIN_RACE_SURA_M: return "SURA_M";
case MAIN_RACE_SHAMAN_W: return "SHAMAN_W";
case MAIN_RACE_WARRIOR_W: return "WARRIOR_W";
case MAIN_RACE_ASSASSIN_M: return "ASSASSIN_M";
case MAIN_RACE_SURA_W: return "SURA_W";
case MAIN_RACE_SHAMAN_M: return "SHAMAN_M";
}
return "UNKNOWN_RACE";
}
const char* FN_weapon_string(int weapon)
{
switch (weapon)
{
case WEAPON_SWORD: return "SWORD";
case WEAPON_DAGGER: return "DAGGER";
case WEAPON_BOW: return "BOW";
case WEAPON_TWO_HANDED: return "TWO_HANDED";
case WEAPON_BELL: return "BELL";
case WEAPON_FAN: return "FAN";
case WEAPON_ARROW: return "ARROW";
case WEAPON_MOUNT_SPEAR:return "WEAPON_MOUNT_SPEAR";
}
return "UNKNOWN";
}
void ANI::print_attack_speed()
{
for (int race = 0; race < MAIN_RACE_MAX_NUM; ++race)
{
for (int weapon = 0; weapon < WEAPON_NUM_TYPES; ++weapon)
{
printf("[%s][%s] = %u\n",
FN_race_string(race),
FN_weapon_string(weapon),
attack_speed(race, weapon));
}
printf("\n");
}
}
void ani_init()
{
s_ANI.load();
}
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));
*/
/* <20><><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD> <20>ҵ<EFBFBD><D2B5><EFBFBD> <20><><EFBFBD><EFBFBD> <20><EFBFBD><EFBFAC><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD> <20>¸<EFBFBD><C2B8><EFBFBD> */
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ѽհ<D1BC> <20>ӵ<EFBFBD><D3B5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
if (weapon == WEAPON_TWO_HANDED)
weapon = WEAPON_SWORD;
return s_ANI.attack_speed(race, weapon);
}
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());
}
void ani_print_attack_speed()
{
s_ANI.print_attack_speed();
}
#if 0
int main(int argc, char **argv)
{
ani_init();
ani_print_attack_speed();
exit(0);
}
#endif

19
game/src/ani.h Normal file
View File

@ -0,0 +1,19 @@
/*********************************************************************
* date : 2007.11.16
* file : ani.h
* author : mhh
* description :
*/
#ifndef _ani_h_
#define _ani_h_
void ani_init();
DWORD ani_attack_speed(LPCHARACTER ch);
void ani_print_attack_speed();
DWORD ani_combo_speed(LPCHARACTER ch, BYTE combo);
#endif /* _ani_h_ */

67
game/src/any_function.h Normal file
View File

@ -0,0 +1,67 @@
// See http://www.boost.org/libs/any for Documentation.
#ifndef __IPKN_ANY_FUNCTION_VARIATION_OF_BOOST_ANY_INCLUDED
#define __IPKN_ANY_FUNCTION_VARIATION_OF_BOOST_ANY_INCLUDED
// what: variant type boost::any
// who: contributed by Kevlin Henney,
// with features contributed and bugs found by
// Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
// when: July 2001
// where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
#include <algorithm>
#include <typeinfo>
#define boost _boost_func_of_SQLMsg
#define func_arg_type SQLMsg*
#define func_arg pmsg
#include "any_function.inc"
#undef func_arg
#undef func_arg_type
#undef boost
typedef _boost_func_of_SQLMsg::any any_function;
#define boost _boost_func_of_void
#define func_arg_type
#define func_arg
#include "any_function.inc"
#undef func_arg
#undef func_arg_type
#undef boost
typedef _boost_func_of_void::any any_void_function;
template <class F>
class void_binder
{
protected:
F f;
typename F::argument_type value;
public:
void_binder(const F& f, const typename F::argument_type x)
: f(f), value(x) {}
void operator()() const {
return f(value);
}
};
template <class F, class Arg>
inline void_binder<F> void_bind(const F& f, const Arg& arg)
{
typedef typename F::argument_type arg_type;
return void_binder<F>(f, arg_type(arg));
}
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
//
// This software is provided "as is" without express or implied warranty.
#endif

116
game/src/any_function.inc Normal file
View File

@ -0,0 +1,116 @@
namespace boost
{
class any
{
public: // structors
any()
: content(0)
{
}
template<typename ValueType>
any(const ValueType & value)
: content(new holder<ValueType>(value))
{
}
any(const any & other)
: content(other.content ? other.content->clone() : 0)
{
}
~any()
{
delete content;
}
public: // modifiers
any & swap(any & rhs)
{
std::swap(content, rhs.content);
return *this;
}
template<typename ValueType>
any & operator=(const ValueType & rhs)
{
any(rhs).swap(*this);
return *this;
}
any & operator=(const any & rhs)
{
any(rhs).swap(*this);
return *this;
}
void operator ()(func_arg_type func_arg)
{
(*content)(func_arg);
}
public: // queries
bool empty() const
{
return !content;
}
private: // types
class placeholder
{
public: // structors
virtual ~placeholder()
{
}
public: // queries
virtual placeholder * clone() const = 0;
virtual void operator()(func_arg_type func_arg) = 0;
};
template<typename ValueType>
class holder : public placeholder
{
public: // structors
holder(const ValueType & value)
: held(value)
{
}
public: // queries
virtual placeholder * clone() const
{
return new holder(held);
}
virtual void operator ()(func_arg_type func_arg)
{
held(func_arg);
}
public: // representation
ValueType held;
};
private: // representation
template<typename ValueType>
friend ValueType * any_cast(any *);
placeholder * content;
};
}

1138
game/src/arena.cpp Normal file

File diff suppressed because it is too large Load Diff

139
game/src/arena.h Normal file
View File

@ -0,0 +1,139 @@
#ifndef __CLASS_ARENA_MANAGER__
#define __CLASS_ARENA_MANAGER__
#include <lua.h>
enum MEMBER_IDENTITY
{
MEMBER_NO,
MEMBER_DUELIST,
MEMBER_OBSERVER,
MEMBER_MAX
};
class CArena
{
friend class CArenaMap;
private :
DWORD m_dwPIDA;
DWORD m_dwPIDB;
LPEVENT m_pEvent;
LPEVENT m_pTimeOutEvent;
PIXEL_POSITION m_StartPointA;
PIXEL_POSITION m_StartPointB;
PIXEL_POSITION m_ObserverPoint;
DWORD m_dwSetCount;
DWORD m_dwSetPointOfA;
DWORD m_dwSetPointOfB;
std::map<DWORD, LPCHARACTER> m_mapObserver;
protected :
CArena(WORD startA_X, WORD startA_Y, WORD startB_X, WORD startB_Y);
bool StartDuel(LPCHARACTER pCharFrom, LPCHARACTER pCharTo, int nSetPoint, int nMinute = 5);
bool IsEmpty() const { return ((m_dwPIDA==0) && (m_dwPIDB==0)); }
bool IsMember(DWORD dwPID) const { return ((m_dwPIDA==dwPID) || (m_dwPIDB==dwPID)); }
bool CheckArea(WORD startA_X, WORD startA_Y, WORD startB_X, WORD startB_Y);
void Clear();
bool CanAttack(DWORD dwPIDA, DWORD dwPIDB);
bool OnDead(DWORD dwPIDA, DWORD dwPIDB);
bool IsObserver(DWORD pid);
bool IsMyObserver(WORD ObserverX, WORD ObserverY);
bool AddObserver(LPCHARACTER pChar);
bool RegisterObserverPtr(LPCHARACTER pChar);
public :
DWORD GetPlayerAPID() { return m_dwPIDA; }
DWORD GetPlayerBPID() { return m_dwPIDB; }
LPCHARACTER GetPlayerA() { return CHARACTER_MANAGER::instance().FindByPID(m_dwPIDA); }
LPCHARACTER GetPlayerB() { return CHARACTER_MANAGER::instance().FindByPID(m_dwPIDB); }
PIXEL_POSITION GetStartPointA() { return m_StartPointA; }
PIXEL_POSITION GetStartPointB() { return m_StartPointB; }
PIXEL_POSITION GetObserverPoint() { return m_ObserverPoint; }
void EndDuel();
void ClearEvent() { m_pEvent = NULL; }
void OnDisconnect(DWORD pid);
void RemoveObserver(DWORD pid);
void SendPacketToObserver(const void * c_pvData, int iSize);
void SendChatPacketToObserver(BYTE type, const char * format, ...);
};
class CArenaMap
{
friend class CArenaManager;
private :
DWORD m_dwMapIndex;
std::list<CArena*> m_listArena;
protected :
void Destroy();
bool AddArena(DWORD mapIdx, WORD startA_X, WORD startA_Y, WORD startB_X, WORD startB_Y);
void SendArenaMapListTo(LPCHARACTER pChar, DWORD dwMapIndex);
bool StartDuel(LPCHARACTER pCharFrom, LPCHARACTER pCharTo, int nSetPoint, int nMinute = 5);
void EndAllDuel();
bool EndDuel(DWORD pid);
int GetDuelList(lua_State* L, int index);
bool CanAttack(LPCHARACTER pCharAttacker, LPCHARACTER pCharVictim);
bool OnDead(LPCHARACTER pCharKiller, LPCHARACTER pCharVictim);
bool AddObserver(LPCHARACTER pChar, WORD ObserverX, WORD ObserverY);
bool RegisterObserverPtr(LPCHARACTER pChar, DWORD mapIdx, WORD ObserverX, WORD ObserverY);
MEMBER_IDENTITY IsMember(DWORD PID);
};
class CArenaManager : public singleton<CArenaManager>
{
private :
std::map<DWORD, CArenaMap*> m_mapArenaMap;
public :
bool Initialize();
void Destroy();
bool StartDuel(LPCHARACTER pCharFrom, LPCHARACTER pCharTo, int nSetPoint, int nMinute = 5);
bool AddArena(DWORD mapIdx, WORD startA_X, WORD startA_Y, WORD startB_X, WORD startB_Y);
void SendArenaMapListTo(LPCHARACTER pChar);
void EndAllDuel();
bool EndDuel(DWORD pid);
void GetDuelList(lua_State* L);
bool CanAttack(LPCHARACTER pCharAttacker, LPCHARACTER pCharVictim);
bool OnDead(LPCHARACTER pCharKiller, LPCHARACTER pCharVictim);
bool AddObserver(LPCHARACTER pChar, DWORD mapIdx, WORD ObserverX, WORD ObserverY);
bool RegisterObserverPtr(LPCHARACTER pChar, DWORD mapIdx, WORD ObserverX, WORD ObserverY);
bool IsArenaMap(DWORD dwMapIndex);
MEMBER_IDENTITY IsMember(DWORD dwMapIndex, DWORD PID);
bool IsLimitedItem( long lMapIndex, DWORD dwVnum );
};
#endif /*__CLASS_ARENA_MANAGER__*/

1378
game/src/auction_manager.cpp Normal file

File diff suppressed because it is too large Load Diff

218
game/src/auction_manager.h Normal file
View File

@ -0,0 +1,218 @@
#ifndef __INC_AUCTION_MANAGER_H
#define __INC_AUCTION_MANAGER_H
#include "../../libsql/AsyncSQL.h"
#include "../../common/auction_table.h"
#include <boost/unordered_map.hpp>
#include <algorithm>
#define GRADE_LOW 30
#define GRADE_MID 60
#define GRADE_HIGH 90
template<>
class hash<std::pair <DWORD, DWORD> >
{ // hash functor
public:
typedef std::pair <DWORD, DWORD> _Kty;
size_t operator()(const _Kty& _Keyval) const
{ // hash _Keyval to size_t value by pseudorandomizing transform
ldiv_t _Qrem = ldiv((size_t)_Keyval.first + (size_t)_Keyval.second, 127773);
_Qrem.rem = 16807 * _Qrem.rem - 2836 * _Qrem.quot;
if (_Qrem.rem < 0)
_Qrem.rem += 2147483647;
return ((size_t)_Qrem.rem);
}
};
bool CompareItemInfoByItemNameAC (TAuctionItemInfo* i, TAuctionItemInfo* j);
bool CompareItemInfoByItemNameDC (TAuctionItemInfo* i, TAuctionItemInfo* j);
bool CompareItemInfoByCategoryAC (TAuctionItemInfo* i, TAuctionItemInfo* j);
bool CompareItemInfoByCategoryDC (TAuctionItemInfo* i, TAuctionItemInfo* j);
bool CompareItemInfoByTimeAC (TAuctionItemInfo* i, TAuctionItemInfo* j);
bool CompareItemInfoByTimeDC (TAuctionItemInfo* i, TAuctionItemInfo* j);
bool CompareItemInfoByCharNameAC (TAuctionItemInfo* i, TAuctionItemInfo* j);
bool CompareItemInfoByCharNameDC (TAuctionItemInfo* i, TAuctionItemInfo* j);
bool CompareItemInfoByPriceAC (TAuctionItemInfo* i, TAuctionItemInfo* j);
bool CompareItemInfoByPriceDC (TAuctionItemInfo* i, TAuctionItemInfo* j);
class AuctionBoard
{
public:
AuctionBoard() {}
~AuctionBoard() {}
TAuctionItemInfo* GetItemInfo (DWORD key);
bool DeleteItemInfo (DWORD key);
bool InsertItemInfo (TAuctionItemInfo* item_info);
bool UpdateItemInfo (TAuctionItemInfo* item_info);
private:
typedef boost::unordered_map <DWORD, TAuctionItemInfo*> TItemInfoMap;
TItemInfoMap item_map;
typedef std::map <DWORD, TAuctionItemInfo*> TItemMap;
typedef boost::unordered_map <DWORD, TItemMap*> TPCMap;
TPCMap offer_map;
// sorting<6E><67> <20><><EFBFBD><EFBFBD> members
public:
typedef std::vector <TAuctionItemInfo*> TItemInfoVec;
private:
typedef std::map <std::string, TItemInfoVec*> SortByItemName;
SortByItemName item_name_map;
void Sort(TItemInfoVec& vec, BYTE order);
public:
void SortedItemInfos (TItemInfoVec& vec, BYTE grade, BYTE category, int start_idx, BYTE size, BYTE order[5]);
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Լ<EFBFBD>.
void YourItemInfoList (TItemInfoVec& vec, DWORD player_id, int start_idx, BYTE size);
};
class SaleBoard
{
private:
typedef boost::unordered_map <DWORD, TSaleItemInfo*> TItemInfoMap;
TItemInfoMap item_map;
typedef std::map <DWORD, TSaleItemInfo*> TItemMap;
typedef boost::unordered_map <DWORD, TItemMap*> TPCMap;
TPCMap wisher_map;
TPCMap seller_map;
bool DeleteFromPCMap (TPCMap& pc_map, DWORD player_id, DWORD item_id);
bool InsertInPCMap (TPCMap& pc_map, DWORD player_id, TSaleItemInfo* item_info);
public:
SaleBoard() {}
~SaleBoard() {}
typedef std::vector <TSaleItemInfo*> TItemInfoVec;
void WisherItemInfoList (TItemInfoVec& vec, DWORD wisher_id, int start_idx, BYTE size);
TSaleItemInfo* GetItemInfo (DWORD key);
bool DeleteItemInfo (DWORD key);
bool InsertItemInfo (TSaleItemInfo* item_info);
};
class WishBoard
{
private:
typedef std::map <DWORD, TWishItemInfo*> TItemMap;
typedef boost::unordered_map <DWORD, TItemMap*> TPCMap;
TPCMap wisher_map;
public:
typedef TWishItemInfo ItemInfo;
WishBoard() {}
~WishBoard() {}
TWishItemInfo* GetItemInfo (DWORD wisher_id, DWORD item_num);
bool DeleteItemInfo (DWORD wisher_id, DWORD item_num);
bool InsertItemInfo (TWishItemInfo* item_info);
};
class MyBidBoard
{
private:
typedef std::pair <int, bool> BidInfo;
typedef std::map <DWORD, BidInfo > TItemMap;
typedef boost::unordered_map <DWORD, TItemMap*> TMyBidBoard;
// bidder_id<69><64> key
TMyBidBoard pc_map;
public:
MyBidBoard() {}
~MyBidBoard() {}
typedef std::vector <DWORD> TItemVec;
void YourBidInfo (TItemVec& vec, DWORD bidder_id, int start_idx, int size);
BidInfo GetMoney (DWORD player_id, DWORD item_id);
bool Delete (DWORD player_id, DWORD item_id);
// <20>̹<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
void Insert (DWORD player_id, DWORD item_id, int money);
void Lock (DWORD player_id, DWORD item_id);
void UnLock (DWORD player_id, DWORD item_id);
};
class AuctionManager : public singleton <AuctionManager>
{
private :
typedef boost::unordered_map<DWORD, LPITEM> TItemMap;
TItemMap auction_item_map;
// auction<6F><6E> <20><><EFBFBD>ϵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>̺<EFBFBD><CCBA><EFBFBD> <20><><EFBFBD>Ե<EFBFBD><D4B5><EFBFBD> <20>ʴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>͵<EFBFBD>
AuctionBoard Auction;
SaleBoard Sale;
WishBoard Wish;
MyBidBoard MyBid;
public:
bool InsertItem (LPITEM item);
bool InsertItem (TPlayerItem* player_item);
LPITEM GetInventoryItem (DWORD item_id);
bool DeleteItem (DWORD item_id);
bool InsertAuctionItemInfo (TAuctionItemInfo* item_info);
TAuctionItemInfo* GetAuctionItemInfo (DWORD item_id)
{
return Auction.GetItemInfo (item_id);
}
bool InsertSaleItemInfo (TSaleItemInfo* item_info);
TSaleItemInfo* GetSaleItemInfo (DWORD item_id)
{
return Sale.GetItemInfo (item_id);
}
bool InsertWishItemInfo (TWishItemInfo* item_info);
TWishItemInfo* GetWishItemInfo (DWORD wisher_id, DWORD item_id)
{
return Wish.GetItemInfo (wisher_id, item_id);
}
void YourBidItemInfoList (AuctionBoard::TItemInfoVec& vec, DWORD bidder_id, int start_idx, int size);
void Boot (const char* &pdata, WORD size);
void get_auction_list (LPCHARACTER ch, int start_idx, int size, int cond);
void get_my_auction_list (LPCHARACTER ch, int start_idx, int size);
void get_my_purchase_list (LPCHARACTER ch, int start_idx, int size);
void enroll_auction (LPCHARACTER ch, LPITEM item, BYTE empire, int bidPrice, int immidiatePurchasePrice);
void recv_result_auction (DWORD commander_id, TPacketDGResultAuction* cmd_result);
void bid (LPCHARACTER ch, DWORD item_id, int price);
void immediate_purchase (LPCHARACTER ch, DWORD item_id);
void enroll_sale (LPCHARACTER ch, LPITEM item, DWORD wisher_id, int salePrice);
void enroll_wish (LPCHARACTER ch, DWORD item_num, BYTE empire, int wishPrice);
void get_auctioned_item (LPCHARACTER ch, DWORD item_id, DWORD item_num);
void buy_sold_item (LPCHARACTER ch, DWORD item_id);
void cancel_auction (LPCHARACTER ch, DWORD item_id);
void cancel_wish (LPCHARACTER ch, DWORD item_num);
void cancel_sale (LPCHARACTER ch, DWORD item_id);
void rebid (LPCHARACTER ch, DWORD item_id, int price);
void bid_cancel (LPCHARACTER ch, DWORD item_id);
/*
void close_auction (LPCHARACTER ch);*/
};
#endif

View File

@ -0,0 +1,5 @@
typedef struct packet_auction_simple_item_info
{
BYTE header;
BYTE size;
} TPacketGCAuctionItemSimpleInfo;

182
game/src/auth_brazil.cpp Normal file
View File

@ -0,0 +1,182 @@
/* vi: set sw=4 ts=8 cino=g0,\:0 : */
/*********************************************************************
* date : 2010.4.7
* file : auth_brazil.c
* author : mhh
* description :
*/
#include "stdafx.h"
#ifndef __WIN32__
#include <unistd.h>
#include <stdint.h>
#endif
#include <stdio.h>
#include <string.h>
#ifdef __FreeBSD__
#include <md5.h>
#else
#include "../../libthecore/include/xmd5.h"
#endif
#include "auth_brazil.h"
static const char* FN_md5(const char *src)
{
static char s_buffer[512];
memset(s_buffer, 0x00, sizeof(s_buffer));
unsigned char digest[16] = {0};
MD5_CTX md5;
MD5Init(&md5);
MD5Update(&md5, (const unsigned char*) src, strlen(src));
MD5Final(digest, &md5);
int offset = 0;
for (int i=0; i<16; ++i) {
offset += sprintf(s_buffer + offset, "%02x", digest[i]);
}
return s_buffer;
}
static int FN_make_request(const char *login, const char *password, /*out*/ char *dst, int dst_size)
{
int len = snprintf(dst, dst_size,
// "GET /metin2/game_auth.php?ID=%s&PW=%s HTTP/1.1\r\n"
"GET /metin2/?ID=%s&PW=%s HTTP/1.1\r\n"
"Host: auth.ongame.com.br\r\n"
"Connection: Close\r\n\r\n",
login, FN_md5(password));
return len;
}
static int FN_parse_reply(char *reply)
{
char buffer[2048];
strlcpy(buffer, reply, sizeof(buffer));
const char *delim = "\r\n";
char *last = 0;
char *v = strtok_r(buffer, delim, &last);
char *result = 0;
while (v)
{
result = v;
v = strtok_r(NULL, delim, &last);
}
if (result)
{
if (0 == strcasecmp("true", result))
return AUTH_BRAZIL_SUCC;
else if (0 == strcasecmp("false", result))
return AUTH_BRAZIL_WRONGPWD;
else if (0 == strcasecmp("unknown", result))
return AUTH_BRAZIL_NOID;
else if (0 == strcasecmp("flash", result))
return AUTH_BRAZIL_FLASHUSER;
}
return AUTH_BRAZIL_SERVER_ERR;
}
extern void socket_timeout(socket_t s, long sec, long usec);
int auth_brazil(const char *login, const char *pwd)
{
const char *host = "auth.ongame.com.br";
int port = 80;
socket_t fd = socket_connect(host, port);
if (fd < 0)
{
sys_err("[AUTH_BRAZIL] : could not connect to gsp server(%s)", host);
return AUTH_BRAZIL_SERVER_ERR;
}
socket_block(fd);
socket_timeout(fd, 3, 0);
// send request
{
char request[512];
int len = FN_make_request(login, pwd, request, sizeof(request));
#ifndef __WIN32__
if (write(fd, request, len) < 0)
#else
if (_write(fd, request, len) < 0)
#endif
{
sys_err("[AUTH_BRAZIL] : could not send auth-request (%s)", login);
close(fd);
return AUTH_BRAZIL_SERVER_ERR;
}
}
// read reply
{
char reply[1024] = {0};
int len = read(fd, reply, sizeof(reply));
close(fd);
if (len <= 0)
{
sys_err("[AUTH_BRAZIL] : could not recv auth-reply (%s)", login);
return AUTH_BRAZIL_SERVER_ERR;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><ECBFA1> query count<6E><74> <20>ø<EFBFBD><C3B8><EFBFBD>.
auth_brazil_inc_query_count();
return FN_parse_reply(reply);
}
}
static int s_query_count = 0;
int auth_brazil_inc_query_count()
{
return ++s_query_count;
}
void auth_brazil_log()
{
FILE *fp = 0;
// open and try backup
{
fp = fopen("AUTH_COUNT.log", "a");
if (0 == fp)
return;
struct stat sb;
fstat(fileno(fp), &sb);
if (sb.st_size > 1024 * 1024)
{
fclose(fp);
rename("AUTH_COUNT.log", "AUTH_COUNT.log.old");
fp = fopen("AUTH_COUNT.log", "a");
}
}
// write log
{
fprintf(fp, "%d\n", s_query_count);
fclose(fp);
}
// reset query count
s_query_count = 0;
}

23
game/src/auth_brazil.h Normal file
View File

@ -0,0 +1,23 @@
/* vi: set sw=4 ts=8 cino=g0,\:0 : */
/*********************************************************************
* date : 2010.4.7
* file : auth_brazil.h
* author : mhh
* description :
*/
#ifndef __auth_brazil_h_1270647899__
#define __auth_brazil_h_1270647899__
#define AUTH_BRAZIL_SERVER_ERR 0
#define AUTH_BRAZIL_SUCC 1
#define AUTH_BRAZIL_NOID 2
#define AUTH_BRAZIL_WRONGPWD 3
#define AUTH_BRAZIL_FLASHUSER 4
int auth_brazil(const char *login, const char *pwd);
int auth_brazil_inc_query_count();
void auth_brazil_log();
#endif // __auth_brazil_h_1270647899__

126
game/src/banword.cpp Normal file
View File

@ -0,0 +1,126 @@
#include "stdafx.h"
#include "constants.h"
#include "banword.h"
#include "config.h"
extern void SendLog(const char * c_pszBuf); // <20><EFBFBD>ڿ<EFBFBD><DABF>Ը<EFBFBD> <20><><EFBFBD><EFBFBD>
CBanwordManager::CBanwordManager()
{
}
CBanwordManager::~CBanwordManager()
{
}
bool CBanwordManager::Initialize(TBanwordTable * p, WORD wSize)
{
m_hashmap_words.clear();
for (WORD i = 0; i < wSize; ++i, ++p)
m_hashmap_words[p->szWord] = true;
char szBuf[256];
snprintf(szBuf, sizeof(szBuf), "Banword reloaded! (total %zu banwords)", m_hashmap_words.size());
SendLog(szBuf);
return true;
}
bool CBanwordManager::Find(const char * c_pszString)
{
return m_hashmap_words.end() != m_hashmap_words.find(c_pszString);
}
bool CBanwordManager::CheckString(const char * c_pszString, size_t _len)
{
if (m_hashmap_words.empty())
return false;
typeof(m_hashmap_words.begin()) it = m_hashmap_words.begin();
while (it != m_hashmap_words.end())
{
const std::string & r = it->first;
const char * tmp = c_pszString;
ssize_t len = _len;
while (len > 0)
{
if (is_twobyte(tmp))
{
if (!strncmp(tmp, r.c_str(), r.size()))
return true;
tmp += 2;
len -= 2;
}
else
{
if (!strncmp(tmp, r.c_str(), r.size()))
return true;
++tmp;
--len;
}
}
it++;
}
return false;
}
void CBanwordManager::ConvertString(char * c_pszString, size_t _len)
{
typeof(m_hashmap_words.begin()) it = m_hashmap_words.begin();
while (it != m_hashmap_words.end())
{
const std::string & r = it->first;
char * tmp = c_pszString;
ssize_t len = _len;
while (len > 0)
{
if (is_twobyte(tmp))
{
if (!strncmp(tmp, r.c_str(), r.size()))
{
memset(tmp, '*', r.size());
tmp += r.size();
len -= r.size();
}
else
{
tmp += 2;
len -= 2;
}
}
else
{
if (*tmp == '*')
{
++tmp;
--len;
continue;
}
if (!strncmp(tmp, r.c_str(), r.size()))
{
memset(tmp, '*', r.size());
tmp += r.size();
len -= r.size();
}
else
{
++tmp;
--len;
}
}
}
it++;
}
}

24
game/src/banword.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef BANWORD_MANAGER_H_
#define BANWORD_MANAGER_H_
#include <boost/unordered_map.hpp>
class CBanwordManager : public singleton<CBanwordManager>
{
public:
CBanwordManager();
virtual ~CBanwordManager();
bool Initialize(TBanwordTable * p, WORD wSize);
bool Find(const char * c_pszString);
bool CheckString(const char * c_pszString, size_t _len);
void ConvertString(char * c_pszString, size_t _len);
protected:
typedef boost::unordered_map<std::string, bool> TBanwordHashmap;
TBanwordHashmap m_hashmap_words;
};
#endif /* BANWORD_MANAGER_H_ */

823
game/src/battle.cpp Normal file
View File

@ -0,0 +1,823 @@
#include "stdafx.h"
#include "utils.h"
#include "config.h"
#include "desc.h"
#include "char.h"
#include "char_manager.h"
#include "battle.h"
#include "item.h"
#include "item_manager.h"
#include "mob_manager.h"
#include "vector.h"
#include "packet.h"
#include "pvp.h"
#include "profiler.h"
#include "guild.h"
#include "affect.h"
#include "unique_item.h"
#include "lua_incl.h"
#include "arena.h"
#include "castle.h"
#include "sectree.h"
#include "ani.h"
#include "locale_service.h"
int battle_hit(LPCHARACTER ch, LPCHARACTER victim, int & iRetDam);
bool battle_distance_valid_by_xy(long x, long y, long tx, long ty)
{
long distance = DISTANCE_APPROX(x - tx, y - ty);
if (distance > 170)
return false;
return true;
}
bool battle_distance_valid(LPCHARACTER ch, LPCHARACTER victim)
{
return battle_distance_valid_by_xy(ch->GetX(), ch->GetY(), victim->GetX(), victim->GetY());
}
bool timed_event_cancel(LPCHARACTER ch)
{
if (ch->m_pkTimedEvent)
{
event_cancel(&ch->m_pkTimedEvent);
return true;
}
/* RECALL_DELAY
<20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF> <20><><EFBFBD><EFBFBD><EFBFBD>̰<EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD><C7BE><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20>ּ<EFBFBD> <20><><EFBFBD><EFBFBD>
if (ch->m_pk_RecallEvent)
{
event_cancel(&ch->m_pkRecallEvent);
return true;
}
END_OF_RECALL_DELAY */
return false;
}
bool battle_is_attackable(LPCHARACTER ch, LPCHARACTER victim)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>׾<EFBFBD><D7BE><EFBFBD><EFBFBD><EFBFBD> <20>ߴ<EFBFBD><DFB4>Ѵ<EFBFBD>.
if (victim->IsDead())
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ߴ<EFBFBD>
{
SECTREE *sectree = NULL;
sectree = ch->GetSectree();
if (sectree && sectree->IsAttr(ch->GetX(), ch->GetY(), ATTR_BANPK))
return false;
sectree = victim->GetSectree();
if (sectree && sectree->IsAttr(victim->GetX(), victim->GetY(), ATTR_BANPK))
return false;
}
// <20><><EFBFBD><EFBFBD> <20>׾<EFBFBD><D7BE><EFBFBD><EFBFBD><EFBFBD> <20>ߴ<EFBFBD><DFB4>Ѵ<EFBFBD>.
if (ch->IsStun() || ch->IsDead())
return false;
if (ch->IsPC() && victim->IsPC())
{
CGuild* g1 = ch->GetGuild();
CGuild* g2 = victim->GetGuild();
if (g1 && g2)
{
if (g1->UnderWar(g2->GetID()))
return true;
}
}
if (IS_CASTLE_MAP(ch->GetMapIndex()) && false==castle_can_attack(ch, victim))
return false;
if (CArenaManager::instance().CanAttack(ch, victim) == true)
return true;
return CPVPManager::instance().CanAttack(ch, victim);
}
int battle_melee_attack(LPCHARACTER ch, LPCHARACTER victim)
{
if (test_server&&ch->IsPC())
sys_log(0, "battle_melee_attack : [%s] attack to [%s]", ch->GetName(), victim->GetName());
if (!victim || ch == victim)
return BATTLE_NONE;
if (test_server&&ch->IsPC())
sys_log(0, "battle_melee_attack : [%s] attack to [%s]", ch->GetName(), victim->GetName());
if (!battle_is_attackable(ch, victim))
return BATTLE_NONE;
if (test_server&&ch->IsPC())
sys_log(0, "battle_melee_attack : [%s] attack to [%s]", ch->GetName(), victim->GetName());
// <20>Ÿ<EFBFBD> üũ
int distance = DISTANCE_APPROX(ch->GetX() - victim->GetX(), ch->GetY() - victim->GetY());
if (!victim->IsBuilding())
{
int max = 300;
if (false == ch->IsPC())
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ÿ<EFBFBD><C5B8><EFBFBD> <20><><EFBFBD><EFBFBD>
max = (int) (ch->GetMobAttackRange() * 1.15f);
}
else
{
// PC<50><43> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>밡 melee <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ÿ<EFBFBD><C5B8><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ÿ<EFBFBD>
if (false == victim->IsPC() && BATTLE_TYPE_MELEE == victim->GetMobBattleType())
max = MAX(300, (int) (victim->GetMobAttackRange() * 1.15f));
}
if (distance > max)
{
if (test_server)
sys_log(0, "VICTIM_FAR: %s distance: %d max: %d", ch->GetName(), distance, max);
return BATTLE_NONE;
}
}
if (timed_event_cancel(ch))
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
if (timed_event_cancel(victim))
victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
ch->SetPosition(POS_FIGHTING);
ch->SetVictim(victim);
const PIXEL_POSITION & vpos = victim->GetXYZ();
ch->SetRotationToXY(vpos.x, vpos.y);
int dam;
int ret = battle_hit(ch, victim, dam);
return (ret);
}
// <20><><EFBFBD><EFBFBD> GET_BATTLE_VICTIM<49><4D> NULL<4C><4C> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>̺<EFBFBD>Ʈ<EFBFBD><C6AE> ĵ<><C4B5> <20><>Ų<EFBFBD><C5B2>.
void battle_end_ex(LPCHARACTER ch)
{
if (ch->IsPosition(POS_FIGHTING))
ch->SetPosition(POS_STANDING);
}
void battle_end(LPCHARACTER ch)
{
battle_end_ex(ch);
}
// AG = Attack Grade
// AL = Attack Limit
int CalcBattleDamage(int iDam, int iAttackerLev, int iVictimLev)
{
if (iDam < 3)
iDam = number(1, 5);
//return CALCULATE_DAMAGE_LVDELTA(iAttackerLev, iVictimLev, iDam);
return iDam;
}
int CalcMagicDamageWithValue(int iDam, LPCHARACTER pkAttacker, LPCHARACTER pkVictim)
{
return CalcBattleDamage(iDam, pkAttacker->GetLevel(), pkVictim->GetLevel());
}
int CalcMagicDamage(LPCHARACTER pkAttacker, LPCHARACTER pkVictim)
{
int iDam = 0;
if (pkAttacker->IsNPC())
{
iDam = CalcMeleeDamage(pkAttacker, pkVictim, false, false);
}
iDam += pkAttacker->GetPoint(POINT_PARTY_ATTACKER_BONUS);
return CalcMagicDamageWithValue(iDam, pkAttacker, pkVictim);
}
float CalcAttackRating(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, bool bIgnoreTargetRating)
{
int iARSrc;
int iERSrc;
if (LC_IsYMIR()) // õ<><C3B5>
{
iARSrc = MIN(90, pkAttacker->GetPolymorphPoint(POINT_DX));
iERSrc = MIN(90, pkVictim->GetPolymorphPoint(POINT_DX));
}
else
{
int attacker_dx = pkAttacker->GetPolymorphPoint(POINT_DX);
int attacker_lv = pkAttacker->GetLevel();
int victim_dx = pkVictim->GetPolymorphPoint(POINT_DX);
int victim_lv = pkAttacker->GetLevel();
iARSrc = MIN(90, (attacker_dx * 4 + attacker_lv * 2) / 6);
iERSrc = MIN(90, (victim_dx * 4 + victim_lv * 2) / 6);
}
float fAR = ((float) iARSrc + 210.0f) / 300.0f; // fAR = 0.7 ~ 1.0
if (bIgnoreTargetRating)
return fAR;
// ((Edx * 2 + 20) / (Edx + 110)) * 0.3
float fER = ((float) (iERSrc * 2 + 5) / (iERSrc + 95)) * 3.0f / 10.0f;
return fAR - fER;
}
int CalcAttBonus(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, int iAtk)
{
// PvP<76><50><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (!pkVictim->IsPC())
iAtk += pkAttacker->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_ATTACK_BONUS);
// PvP<76><50><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (!pkAttacker->IsPC())
{
int iReduceDamagePct = pkVictim->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_TRANSFER_DAMAGE);
iAtk = iAtk * (100 + iReduceDamagePct) / 100;
}
if (pkAttacker->IsNPC() && pkVictim->IsPC())
{
iAtk = (iAtk * CHARACTER_MANAGER::instance().GetMobDamageRate(pkAttacker)) / 100;
}
if (pkVictim->IsNPC())
{
if (pkVictim->IsRaceFlag(RACE_FLAG_ANIMAL))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ANIMAL)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_UNDEAD))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_UNDEAD)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_DEVIL))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_DEVIL)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_HUMAN))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_HUMAN)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_ORC))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ORC)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_MILGYO))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_MILGYO)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_INSECT))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_INSECT)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_FIRE))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_FIRE)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_ICE))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ICE)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_DESERT))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_DESERT)) / 100;
else if (pkVictim->IsRaceFlag(RACE_FLAG_TREE))
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_TREE)) / 100;
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_MONSTER)) / 100;
}
else if (pkVictim->IsPC())
{
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_HUMAN)) / 100;
switch (pkVictim->GetJob())
{
case JOB_WARRIOR:
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_WARRIOR)) / 100;
break;
case JOB_ASSASSIN:
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ASSASSIN)) / 100;
break;
case JOB_SURA:
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_SURA)) / 100;
break;
case JOB_SHAMAN:
iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_SHAMAN)) / 100;
break;
}
}
if (pkAttacker->IsPC() == true)
{
switch (pkAttacker->GetJob())
{
case JOB_WARRIOR:
iAtk -= (iAtk * pkVictim->GetPoint(POINT_RESIST_WARRIOR)) / 100;
break;
case JOB_ASSASSIN:
iAtk -= (iAtk * pkVictim->GetPoint(POINT_RESIST_ASSASSIN)) / 100;
break;
case JOB_SURA:
iAtk -= (iAtk * pkVictim->GetPoint(POINT_RESIST_SURA)) / 100;
break;
case JOB_SHAMAN:
iAtk -= (iAtk * pkVictim->GetPoint(POINT_RESIST_SHAMAN)) / 100;
break;
}
}
//[ mob -> PC ] <20><><EFBFBD><EFBFBD> <20>Ӽ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
//2013/01/17
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ӽ<EFBFBD><D3BC><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 30%<25><> <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20><>ġ<EFBFBD><C4A1><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
if (pkAttacker->IsNPC() && pkVictim->IsPC())
{
if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_ELEC))
iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_ELEC)) / 10000;
else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_FIRE))
iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_FIRE)) / 10000;
else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_ICE))
iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_ICE)) / 10000;
else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_WIND))
iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_WIND)) / 10000;
else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_EARTH))
iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_EARTH)) / 10000;
else if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_DARK))
iAtk -= (iAtk * 30 * pkVictim->GetPoint(POINT_RESIST_DARK)) / 10000;
}
return iAtk;
}
void Item_GetDamage(LPITEM pkItem, int* pdamMin, int* pdamMax)
{
*pdamMin = 0;
*pdamMax = 1;
if (!pkItem)
return;
switch (pkItem->GetType())
{
case ITEM_ROD:
case ITEM_PICK:
return;
}
if (pkItem->GetType() != ITEM_WEAPON)
sys_err("Item_GetDamage - !ITEM_WEAPON vnum=%d, type=%d", pkItem->GetOriginalVnum(), pkItem->GetType());
*pdamMin = pkItem->GetValue(3);
*pdamMax = pkItem->GetValue(4);
}
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());
}
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;
// Ÿ<><C5B8>ġ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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;
}
void NormalAttackAffect(LPCHARACTER pkAttacker, LPCHARACTER pkVictim)
{
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ư<><C6AF><EFBFBD>ϹǷ<CFB9> Ư<><C6AF> ó<><C3B3>
if (pkAttacker->GetPoint(POINT_POISON_PCT) && !pkVictim->IsAffectFlag(AFF_POISON))
{
if (number(1, 100) <= pkAttacker->GetPoint(POINT_POISON_PCT))
pkVictim->AttackedByPoison(pkAttacker);
}
int iStunDuration = 2;
if (pkAttacker->IsPC() && !pkVictim->IsPC())
iStunDuration = 4;
AttackAffect(pkAttacker, pkVictim, POINT_STUN_PCT, IMMUNE_STUN, AFFECT_STUN, POINT_NONE, 0, AFF_STUN, iStunDuration, "STUN");
AttackAffect(pkAttacker, pkVictim, POINT_SLOW_PCT, IMMUNE_SLOW, AFFECT_SLOW, POINT_MOV_SPEED, -30, AFF_SLOW, 20, "SLOW");
}
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);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
//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;
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. (2011<31><31> 2<><32> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>հŹ̿<C5B9><CCBF>Ը<EFBFBD> <20><><EFBFBD><EFBFBD>.)
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 GET_ATTACK_SPEED(LPCHARACTER ch)
{
if (NULL == ch)
return 1000;
LPITEM item = ch->GetWear(WEAR_WEAPON);
DWORD default_bonus = SPEEDHACK_LIMIT_BONUS * 3; // <20><><EFBFBD>θ<EFBFBD> <20><><EFBFBD><EFBFBD>(<28>⺻ 80) (<28>Ϲ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> speed hack <20><> <20>ɸ<EFBFBD><C9B8><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> *3 <20>߰<EFBFBD>. 2013.09.11 CYH)
DWORD riding_bonus = 0;
if (ch->IsRiding())
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߰<EFBFBD><DFB0><EFBFBD><EFBFBD><EFBFBD> 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);
// <20>ܰ<EFBFBD><DCB0><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> 2<><32>
if (item && item->GetSubType() == WEAPON_DAGGER)
real_speed /= 2;
return real_speed;
}
void SET_ATTACK_TIME(LPCHARACTER ch, LPCHARACTER victim, DWORD current_time)
{
if (NULL == ch || NULL == victim)
return;
if (!ch->IsPC())
return;
ch->m_kAttackLog.dwVID = victim->GetVID();
ch->m_kAttackLog.dwTime = current_time;
}
void SET_ATTACKED_TIME(LPCHARACTER ch, LPCHARACTER victim, DWORD current_time)
{
if (NULL == ch || NULL == victim)
return;
if (!ch->IsPC())
return;
victim->m_AttackedLog.dwPID = ch->GetPlayerID();
victim->m_AttackedLog.dwAttackedTime= current_time;
}
bool IS_SPEED_HACK(LPCHARACTER ch, LPCHARACTER victim, DWORD current_time)
{
// 2013 09 11 CYH debugging log
/*sys_log(0, "%s attack test log! time (delta, limit)=(%u, %u). ch->m_kAttackLog.dwvID(%u) victim->GetVID(%u)",
ch->GetName(),
current_time - ch->m_kAttackLog.dwTime,
GET_ATTACK_SPEED(ch),
ch->m_kAttackLog.dwVID,
victim->GetVID()
);
sys_log(0, "%s attack test log! time (delta, limit)=(%u, %u). victim->m_AttackedLog.dwPID(%u) ch->GetPlayerID(%u)",
ch->GetName(),
current_time - victim->m_AttackedLog.dwAttackedTime,
GET_ATTACK_SPEED(ch),
victim->m_AttackedLog.dwPID,
ch->GetPlayerID()
);*/
if (ch->m_kAttackLog.dwVID == victim->GetVID())
{
if (current_time - ch->m_kAttackLog.dwTime < GET_ATTACK_SPEED(ch))
{
INCREASE_SPEED_HACK_COUNT(ch);
if (test_server)
{
sys_log(0, "%s attack hack! time (delta, limit)=(%u, %u) hack_count %d",
ch->GetName(),
current_time - ch->m_kAttackLog.dwTime,
GET_ATTACK_SPEED(ch),
ch->m_speed_hack_count);
ch->ChatPacket(CHAT_TYPE_INFO, "%s attack hack! time (delta, limit)=(%u, %u) hack_count %d",
ch->GetName(),
current_time - ch->m_kAttackLog.dwTime,
GET_ATTACK_SPEED(ch),
ch->m_speed_hack_count);
}
SET_ATTACK_TIME(ch, victim, current_time);
SET_ATTACKED_TIME(ch, victim, current_time);
return true;
}
}
SET_ATTACK_TIME(ch, victim, current_time);
if (victim->m_AttackedLog.dwPID == ch->GetPlayerID())
{
if (current_time - victim->m_AttackedLog.dwAttackedTime < GET_ATTACK_SPEED(ch))
{
INCREASE_SPEED_HACK_COUNT(ch);
if (test_server)
{
sys_log(0, "%s Attack Speed HACK! time (delta, limit)=(%u, %u), hack_count = %d",
ch->GetName(),
current_time - victim->m_AttackedLog.dwAttackedTime,
GET_ATTACK_SPEED(ch),
ch->m_speed_hack_count);
ch->ChatPacket(CHAT_TYPE_INFO, "Attack Speed Hack(%s), (delta, limit)=(%u, %u)",
ch->GetName(),
current_time - victim->m_AttackedLog.dwAttackedTime,
GET_ATTACK_SPEED(ch));
}
SET_ATTACKED_TIME(ch, victim, current_time);
return true;
}
}
SET_ATTACKED_TIME(ch, victim, current_time);
return false;
}

100
game/src/battle.h Normal file
View File

@ -0,0 +1,100 @@
#ifndef __INC_METIN_II_GAME_BATTLE_H__
#define __INC_METIN_II_GAME_BATTLE_H__
#include "char.h"
enum EBattleTypes // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
{
BATTLE_NONE,
BATTLE_DAMAGE,
BATTLE_DEFENSE,
BATTLE_DEAD
};
extern int CalcAttBonus(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, int iAtk);
extern int CalcBattleDamage(int iDam, int iAttackerLev, int iVictimLev);
extern int CalcMeleeDamage(LPCHARACTER pAttacker, LPCHARACTER pVictim, bool bIgnoreDefense = false, bool bIgnoreTargetRating = false);
extern int CalcMagicDamage(LPCHARACTER pAttacker, LPCHARACTER pVictim);
extern int CalcArrowDamage(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, LPITEM pkBow, LPITEM pkArrow, bool bIgnoreDefense = false);
extern float CalcAttackRating(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, bool bIgnoreTargetRating = false);
extern bool battle_is_attackable(LPCHARACTER ch, LPCHARACTER victim);
extern int battle_melee_attack(LPCHARACTER ch, LPCHARACTER victim);
extern void battle_end(LPCHARACTER ch);
extern bool battle_distance_valid_by_xy(long x, long y, long tx, long ty);
extern bool battle_distance_valid(LPCHARACTER ch, LPCHARACTER victim);
extern int battle_count_attackers(LPCHARACTER ch);
extern void NormalAttackAffect(LPCHARACTER pkAttacker, LPCHARACTER pkVictim);
// Ư<><C6AF> <20><><EFBFBD><EFBFBD>
inline void AttackAffect(LPCHARACTER pkAttacker,
LPCHARACTER pkVictim,
BYTE att_point,
DWORD immune_flag,
DWORD affect_idx,
BYTE affect_point,
long affect_amount,
DWORD affect_flag,
int time,
const char* name)
{
if (pkAttacker->GetPoint(att_point) && !pkVictim->IsAffectFlag(affect_flag))
{
if (number(1, 100) <= pkAttacker->GetPoint(att_point) && !pkVictim->IsImmune(immune_flag))
{
pkVictim->AddAffect(affect_idx, affect_point, affect_amount, affect_flag, time, 0, true);
if (test_server)
{
pkVictim->ChatPacket(CHAT_TYPE_PARTY, "%s %s(%ld%%) SUCCESS", pkAttacker->GetName(), name, pkAttacker->GetPoint(att_point));
}
}
else if (test_server)
{
pkVictim->ChatPacket(CHAT_TYPE_PARTY, "%s %s(%ld%%) FAIL", pkAttacker->GetName(), name, pkAttacker->GetPoint(att_point));
}
}
}
inline void SkillAttackAffect(LPCHARACTER pkVictim,
int success_pct,
DWORD immune_flag,
DWORD affect_idx,
BYTE affect_point,
long affect_amount,
DWORD affect_flag,
int time,
const char* name)
{
if (success_pct && !pkVictim->IsAffectFlag(affect_flag))
{
if (number(1, 1000) <= success_pct && !pkVictim->IsImmune(immune_flag))
{
pkVictim->AddAffect(affect_idx, affect_point, affect_amount, affect_flag, time, 0, true);
// SKILL_ATTACK_NO_LOG_TARGET_NAME_FIX
if (test_server)
pkVictim->ChatPacket(CHAT_TYPE_PARTY,
"%s(%d%%) -> %s SUCCESS", name, success_pct, name);
// END_OF_SKILL_ATTACK_LOG_NO_TARGET_NAME_FIX
}
else if (test_server)
{
// SKILL_ATTACK_NO_LOG_TARGET_NAME_FIX
pkVictim->ChatPacket(CHAT_TYPE_PARTY, "%s(%d%%) -> %s FAIL", name, success_pct, name);
// END_OF_SKILL_ATTACK_LOG_NO_TARGET_NAME_FIX
}
}
}
#define GET_SPEED_HACK_COUNT(ch) ((ch)->m_speed_hack_count)
#define INCREASE_SPEED_HACK_COUNT(ch) (++GET_SPEED_HACK_COUNT(ch))
DWORD GET_ATTACK_SPEED(LPCHARACTER ch);
void SET_ATTACK_TIME(LPCHARACTER ch, LPCHARACTER victim, DWORD current_time);
void SET_ATTACKED_TIME(LPCHARACTER ch, LPCHARACTER victim, DWORD current_time);
bool IS_SPEED_HACK(LPCHARACTER ch, LPCHARACTER victim, DWORD current_time);
#endif

View File

@ -0,0 +1,108 @@
#ifndef __HEADER_BELT_INVENTORY_HELPER__
#define __HEADER_BELT_INVENTORY_HELPER__
#include "char.h"
#include "item.h"
class CBeltInventoryHelper
{
public:
typedef BYTE TGradeUnit;
static TGradeUnit GetBeltGradeByRefineLevel(int level)
{
static TGradeUnit beltGradeByLevelTable[] =
{
0, // <20><>Ʈ+0
1, // +1
1, // +2
2, // +3
2, // +4,
3, // +5
4, // +6,
5, // +7,
6, // +8,
7, // +9
};
if (level >= _countof(beltGradeByLevelTable))
{
sys_err("CBeltInventoryHelper::GetBeltGradeByRefineLevel - Overflow level (%d", level);
return 0;
}
return beltGradeByLevelTable[level];
}
// <20><><EFBFBD><EFBFBD> <20><>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> <20><> <20>ִ<EFBFBD><D6B4><EFBFBD> <20><><EFBFBD><EFBFBD>
static const TGradeUnit* GetAvailableRuleTableByGrade()
{
/**
<09><>Ʈ<EFBFBD><C6AE> <20><> +0 ~ +9 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> 7<>ܰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>еǾ<D0B5> <20>κ<EFBFBD><CEBA><EFBFBD><E4B8AE> Ȱ<><C8B0> ȭ <20>ȴ<EFBFBD>.
<09><>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ʒ<EFBFBD> <20>׸<EFBFBD><D7B8><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> >= Ȱ<><C8B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD≯<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
(<28><>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0<≯<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ұ<EFBFBD>, <20><>ȣ <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ڴ<EFBFBD> <20><><EFBFBD><EFBFBD>)
2(1) 4(2) 6(4) 8(6)
5(3) 5(3) 6(4) 8(6)
7(5) 7(5) 7(5) 8(6)
9(7) 9(7) 9(7) 9(7)
<09><>Ʈ <20>κ<EFBFBD><CEBA><EFBFBD><E4B8AE> ũ<><C5A9><EFBFBD><EFBFBD> 4x4 (16ĭ)
*/
static TGradeUnit availableRuleByGrade[BELT_INVENTORY_SLOT_COUNT] = {
1, 2, 4, 6,
3, 3, 4, 6,
5, 5, 5, 6,
7, 7, 7, 7
};
return availableRuleByGrade;
}
static bool IsAvailableCell(WORD cell, int beltGrade /*int beltLevel*/)
{
// <20><>ȹ <20><> <20>ٲ<EFBFBD>.. <20>Ƴ<EFBFBD>...
//const TGradeUnit beltGrade = GetBeltGradeByRefineLevel(beltLevel);
const TGradeUnit* ruleTable = GetAvailableRuleTableByGrade();
return ruleTable[cell] <= beltGrade;
}
/// pc<70><63> <20><>Ʈ <20>κ<EFBFBD><CEBA><EFBFBD><E4B8AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ϳ<EFBFBD><CFB3><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><> <20>˻<EFBFBD><CBBB>ϴ<EFBFBD> <20>Լ<EFBFBD>.
static bool IsExistItemInBeltInventory(LPCHARACTER pc)
{
for (WORD i = BELT_INVENTORY_SLOT_START; i < BELT_INVENTORY_SLOT_END; ++i)
{
LPITEM beltInventoryItem = pc->GetInventoryItem(i);
if (NULL != beltInventoryItem)
return true;
}
return false;
}
/// item<65><6D> <20><>Ʈ <20>κ<EFBFBD><CEBA><EFBFBD><E4B8AE> <20><><EFBFBD><20><> <20>ִ<EFBFBD> Ÿ<><C5B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>˻<EFBFBD><CBBB>ϴ<EFBFBD> <20>Լ<EFBFBD>. (<28><> <20><>Ģ<EFBFBD><C4A2> <20><>ȹ<EFBFBD>ڰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
static bool CanMoveIntoBeltInventory(LPITEM item)
{
bool canMove = false;
if (item->GetType() == ITEM_USE)
{
switch (item->GetSubType())
{
case USE_POTION:
case USE_POTION_NODELAY:
case USE_ABILITY_UP:
canMove = true;
break;
}
}
return canMove;
}
};
#endif //__HEADER_BELT_INVENTORY_HELPER__

249
game/src/blend_item.cpp Normal file
View File

@ -0,0 +1,249 @@
/*********************************************************************
* date : 2007.02.24
* file : blend_item.cpp
* author : mhh
* description :
*/
#define _blend_item_cpp_
#include "stdafx.h"
#include "constants.h"
#include "log.h"
#include "dev_log.h"
#include "locale_service.h"
#include "item.h"
#include "blend_item.h"
#define DO_ALL_BLEND_INFO(iter) for (iter=s_blend_info.begin(); iter!=s_blend_info.end(); ++iter)
struct BLEND_ITEM_INFO
{
DWORD item_vnum;
int apply_type;
int apply_value[MAX_BLEND_ITEM_VALUE];
int apply_duration[MAX_BLEND_ITEM_VALUE];
};
typedef std::vector<BLEND_ITEM_INFO*> T_BLEND_ITEM_INFO;
T_BLEND_ITEM_INFO s_blend_info;
bool Blend_Item_init()
{
BLEND_ITEM_INFO *blend_item_info = NULL;
T_BLEND_ITEM_INFO::iterator iter;
char file_name[256];
snprintf (file_name, sizeof(file_name), "%s/blend.txt", LocaleService_GetBasePath().c_str());
sys_log(0, "Blend_Item_init %s ", file_name);
DO_ALL_BLEND_INFO(iter)
{
blend_item_info = *iter;
M2_DELETE(blend_item_info);
}
s_blend_info.clear();
if (false==Blend_Item_load(file_name))
{
sys_err("<Blend_Item_init> fail");
return false;
}
return true;
}
bool Blend_Item_load(char *file)
{
FILE *fp;
char one_line[256];
const char *delim = " \t\r\n";
char *v;
BLEND_ITEM_INFO *blend_item_info;
if (0==file || 0==file[0])
return false;
if ((fp = fopen(file, "r"))==0)
return false;
while (fgets(one_line, 256, fp))
{
if (one_line[0]=='#')
continue;
const char* token_string = strtok(one_line, delim);
if (NULL==token_string)
continue;
TOKEN("section")
{
blend_item_info = M2_NEW BLEND_ITEM_INFO;
memset(blend_item_info, 0x00, sizeof(BLEND_ITEM_INFO));
}
else TOKEN("item_vnum")
{
v = strtok(NULL, delim);
if (NULL==v)
{
fclose(fp);
return false;
}
str_to_number(blend_item_info->item_vnum, v);
}
else TOKEN("apply_type")
{
v = strtok(NULL, delim);
if (NULL==v)
{
fclose(fp);
return false;
}
if (0 == (blend_item_info->apply_type = FN_get_apply_type(v)))
{
sys_err ("Invalid apply_type(%s)", v);
return false;
}
}
else TOKEN("apply_value")
{
for (int i=0; i<MAX_BLEND_ITEM_VALUE; ++i)
{
v = strtok(NULL, delim);
if (NULL==v)
{
fclose(fp);
return false;
}
str_to_number(blend_item_info->apply_value[i], v);
}
}
else TOKEN("apply_duration")
{
for (int i=0; i<MAX_BLEND_ITEM_VALUE; ++i)
{
v = strtok(NULL, delim);
if (NULL==v)
{
fclose(fp);
return false;
}
str_to_number(blend_item_info->apply_duration[i], v);
}
}
else TOKEN("end")
{
s_blend_info.push_back(blend_item_info);
}
}
fclose(fp);
return true;
}
static int FN_random_index()
{
int percent = number(1,100);
if (percent<=10) // level 1 :10%
return 0;
else if (percent<=30) // level 2 : 20%
return 1;
else if (percent<=70) // level 3 : 40%
return 2;
else if (percent<=90) // level 4 : 20%
return 3;
else
return 4; // level 5 : 10%
return 0;
}
// <20><><EFBFBD><EFBFBD>ȯ<EFBFBD><C8AF> Ȯ<><C8AE> <20><><EFBFBD>̺<EFBFBD>
// blend.txt<78><74><EFBFBD><EFBFBD> Ȯ<><C8AE><EFBFBD><EFBFBD> <20>޵<EFBFBD><DEB5><EFBFBD> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD><CFB0><EFBFBD><EFBFBD><EFBFBD>
// <20><> <20><><EFBFBD>󺰷<EFBFBD> item proto <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϹǷ<CFB9>,
// ȥ<><C8A5><EFBFBD><EFBFBD> <20><> <20><> <20>־<EFBFBD> <20>̷<EFBFBD><CCB7><EFBFBD> <20>߰<EFBFBD><DFB0>Ѵ<EFBFBD>.
// by rtsummit
static int FN_ECS_random_index()
{
int percent = number(1,100);
if (percent<=5) // level 1 : 5%
return 0;
else if (percent<=15) // level 2 : 10%
return 1;
else if (percent<=60) // level 3 : 45%
return 2;
else if (percent<=85) // level 4 : 25%
return 3;
else
return 4; // level 5 : 15%
return 0;
}
bool Blend_Item_set_value(LPITEM item)
{
BLEND_ITEM_INFO *blend_info;
T_BLEND_ITEM_INFO::iterator iter;
DO_ALL_BLEND_INFO(iter)
{
blend_info = *iter;
if (blend_info->item_vnum == item->GetVnum())
{
int apply_type;
int apply_value;
int apply_duration;
if (item->GetVnum() == 51002)
{
apply_type = blend_info->apply_type;
apply_value = blend_info->apply_value [FN_ECS_random_index()];
apply_duration = blend_info->apply_duration [FN_ECS_random_index()];
}
else
{
apply_type = blend_info->apply_type;
apply_value = blend_info->apply_value [FN_random_index()];
apply_duration = blend_info->apply_duration [FN_random_index()];
}
sys_log (0, "blend_item : type : %d, value : %d, du : %d", apply_type, apply_value, apply_duration);
item->SetSocket(0, apply_type);
item->SetSocket(1, apply_value);
item->SetSocket(2, apply_duration);
return true;
}
}
return false;
}
bool Blend_Item_find(DWORD item_vnum)
{
BLEND_ITEM_INFO *blend_info;
T_BLEND_ITEM_INFO::iterator iter;
DO_ALL_BLEND_INFO(iter)
{
blend_info = *iter;
if (blend_info->item_vnum == item_vnum)
return true;
}
return false;
}

20
game/src/blend_item.h Normal file
View File

@ -0,0 +1,20 @@
/*********************************************************************
* date : 2007.02.24
* file : blend_item.h
* author : mhh
* description :
*/
#ifndef _blend_item_h_
#define _blend_item_h_
#define MAX_BLEND_ITEM_VALUE 5
bool Blend_Item_init();
bool Blend_Item_load(char *file);
bool Blend_Item_set_value(LPITEM item);
bool Blend_Item_find(DWORD item_vnum);
#endif /* _blend_item_h_ */

151
game/src/block_country.cpp Normal file
View File

@ -0,0 +1,151 @@
/*********************************************************************
* date : 2007.05.31
* file : block_country.cpp
* author : mhh
* description :
*/
#define _block_country_cpp_
#include "stdafx.h"
#include "constants.h"
#include "block_country.h"
#include "dev_log.h"
#define DEC_ITER(iter) std::vector<T_BLOCK_IP*>::iterator iter
#define DO_ALL_BLOCKED_IP(iter) for ((iter)=s_blocked_ip.begin(); (iter)!=s_blocked_ip.end(); ++(iter))
#define DEC_EXCEPTION_ITER(iter) std::set<std::string>::iterator iter
typedef struct {
DWORD ip_from;
DWORD ip_to;
} T_BLOCK_IP;
//--------------------------------------
// static variables
std::vector<T_BLOCK_IP*> s_blocked_ip;
std::set<std::string> s_block_exception;
// static variables
//--------------------------------------
//--------------------------------------
// static functions
static void __add_block_exception(const char *login)
{
dev_log(LOG_DEB0, "BLOCK_EXCEPTION_ADD : %s", login);
DEC_EXCEPTION_ITER(iter);
std::string string_login(login);
iter = s_block_exception.find(string_login);
// can not find
if (iter==s_block_exception.end())
{
s_block_exception.insert(string_login);
}
}
static void __del_block_exception(const char *login)
{
dev_log(LOG_DEB0, "BLOCK_EXCEPTION_DEL : %s", login);
DEC_EXCEPTION_ITER(iter);
std::string string_login(login);
iter = s_block_exception.find(string_login);
// ok : find
if (iter!=s_block_exception.end())
{
s_block_exception.erase(iter);
}
}
// static functions
//--------------------------------------
void add_blocked_country_ip(TPacketBlockCountryIp *data)
{
T_BLOCK_IP *block_ip = M2_NEW T_BLOCK_IP;
block_ip->ip_from = data->ip_from;
block_ip->ip_to = data->ip_to;
s_blocked_ip.push_back(block_ip);
dev_log(LOG_DEB0, "BLOCKED_IP = %u - %u", block_ip->ip_from, block_ip->ip_to);
}
void block_exception(TPacketBlockException *data)
{
if (NULL==data) return;
if (BLOCK_EXCEPTION_CMD_ADD!=data->cmd && BLOCK_EXCEPTION_CMD_DEL!=data->cmd)
return;
switch (data->cmd)
{
case BLOCK_EXCEPTION_CMD_ADD:
__add_block_exception(data->login);
break;
case BLOCK_EXCEPTION_CMD_DEL:
__del_block_exception(data->login);
break;
}
}
bool is_blocked_country_ip(const char *user_ip)
{
DEC_ITER(iter);
T_BLOCK_IP *block_ip;
DWORD ip_number;
struct in_addr st_addr;
#ifndef __WIN32__
if (0 == inet_aton(user_ip, &st_addr))
#else
unsigned long in_address;
in_address = inet_addr(user_ip);
st_addr.s_addr = in_address;
if (INADDR_NONE == in_address)
#endif
{
dev_log(LOG_INFO, "BLOCKED_COUNTRY_IP (%s) : YES", user_ip);
return true; // <20><><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD>ó<EFBFBD><C3B3>
}
ip_number = htonl(st_addr.s_addr);
DO_ALL_BLOCKED_IP(iter)
{
block_ip = *iter;
if ( block_ip->ip_from <= ip_number && ip_number <= block_ip->ip_to )
{
dev_log(LOG_INFO, "BLOCKED_COUNTRY_IP (%s) : YES", user_ip);
return true;
}
}
dev_log(LOG_INFO, "BLOCKED_COUNTRY_IP (%s) : NO", user_ip);
return false;
}
bool is_block_exception(const char *login)
{
std::string login_string(login);
std::set<std::string>::iterator iter;
iter = s_block_exception.find(login_string);
if (iter != s_block_exception.end())
return true;
return false;
}

18
game/src/block_country.h Normal file
View File

@ -0,0 +1,18 @@
/*********************************************************************
* date : 2007.05.31
* file : block_country.h
* author : mhh
* description :
*/
#ifndef _block_country_h_
#define _block_country_h_
void add_blocked_country_ip(TPacketBlockCountryIp *data);
void block_exception(TPacketBlockException *data);
bool is_blocked_country_ip(const char *user_ip);
bool is_block_exception(const char *login);
#endif // _block_country_h_

View File

@ -0,0 +1,184 @@
#include "stdafx.h"
#include "../../common/tables.h"
#include "item.h"
#include "char.h"
#include "buff_on_attributes.h"
#include <algorithm>
CBuffOnAttributes::CBuffOnAttributes(LPCHARACTER pOwner, BYTE point_type, std::vector <BYTE>* p_vec_buff_wear_targets)
: m_pBuffOwner(pOwner), m_bPointType(point_type), m_p_vec_buff_wear_targets(p_vec_buff_wear_targets)
{
Initialize();
}
CBuffOnAttributes::~CBuffOnAttributes()
{
Off();
}
void CBuffOnAttributes::Initialize()
{
m_bBuffValue = 0;
m_map_additional_attrs.clear();
}
void CBuffOnAttributes::RemoveBuffFromItem(LPITEM pItem)
{
if (0 == m_bBuffValue)
return ;
if (NULL != pItem)
{
if (pItem->GetCell() < INVENTORY_MAX_NUM)
return;
std::vector <BYTE>::iterator it = find (m_p_vec_buff_wear_targets->begin(), m_p_vec_buff_wear_targets->end(), pItem->GetCell() - INVENTORY_MAX_NUM);
if (m_p_vec_buff_wear_targets->end() == it)
return;
int m = pItem->GetAttributeCount();
for (int j = 0; j < m; j++)
{
TPlayerItemAttribute attr = pItem->GetAttribute(j);
TMapAttr::iterator it = m_map_additional_attrs.find(attr.bType);
// m_map_additional_attrs<72><73><EFBFBD><EFBFBD> <20>ش<EFBFBD> attribute type<70><65> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD>,
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (m_bBuffValue)%<25><>ŭ<EFBFBD><C5AD> <20><><EFBFBD><EFBFBD> ȿ<><C8BF> <20><><EFBFBD><EFBFBD>
if (it != m_map_additional_attrs.end())
{
int& sum_of_attr_value = it->second;
int old_value = sum_of_attr_value * m_bBuffValue / 100;
int new_value = (sum_of_attr_value - attr.sValue) * m_bBuffValue / 100;
m_pBuffOwner->ApplyPoint(attr.bType, new_value - old_value);
sum_of_attr_value -= attr.sValue;
}
else
{
sys_err ("Buff ERROR(type %d). This item(%d) attr_type(%d) was not in buff pool", m_bPointType, pItem->GetVnum(), attr.bType);
return;
}
}
}
}
void CBuffOnAttributes::AddBuffFromItem(LPITEM pItem)
{
if (0 == m_bBuffValue)
return ;
if (NULL != pItem)
{
if (pItem->GetCell() < INVENTORY_MAX_NUM)
return;
std::vector <BYTE>::iterator it = find (m_p_vec_buff_wear_targets->begin(), m_p_vec_buff_wear_targets->end(), pItem->GetCell() - INVENTORY_MAX_NUM);
if (m_p_vec_buff_wear_targets->end() == it)
return;
int m = pItem->GetAttributeCount();
for (int j = 0; j < m; j++)
{
TPlayerItemAttribute attr = pItem->GetAttribute(j);
TMapAttr::iterator it = m_map_additional_attrs.find(attr.bType);
// m_map_additional_attrs<72><73><EFBFBD><EFBFBD> <20>ش<EFBFBD> attribute type<70><65> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ٸ<EFBFBD> <20>߰<EFBFBD>.
// <20>߰<EFBFBD><DFB0><EFBFBD> <20><><EFBFBD><EFBFBD> (m_bBuffValue)%<25><>ŭ<EFBFBD><C5AD> <20><><EFBFBD><EFBFBD> ȿ<><C8BF> <20>߰<EFBFBD>
if (it == m_map_additional_attrs.end())
{
m_pBuffOwner->ApplyPoint(attr.bType, attr.sValue * m_bBuffValue / 100);
m_map_additional_attrs.insert(TMapAttr::value_type(attr.bType, attr.sValue));
}
// m_map_additional_attrs<72><73><EFBFBD><EFBFBD> <20>ش<EFBFBD> attribute type<70><65> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ִٸ<D6B4>, <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ű<EFBFBD><C5B0>,
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> (m_bBuffValue)%<25><>ŭ<EFBFBD><C5AD> <20><><EFBFBD><EFBFBD> ȿ<><C8BF> <20>߰<EFBFBD>
else
{
int& sum_of_attr_value = it->second;
int old_value = sum_of_attr_value * m_bBuffValue / 100;
int new_value = (sum_of_attr_value + attr.sValue) * m_bBuffValue / 100;
m_pBuffOwner->ApplyPoint(attr.bType, new_value - old_value);
sum_of_attr_value += attr.sValue;
}
}
}
}
void CBuffOnAttributes::ChangeBuffValue(BYTE bNewValue)
{
if (0 == m_bBuffValue)
On(bNewValue);
else if (0 == bNewValue)
Off();
else
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, m_map_additional_attrs<72><73> <20><><EFBFBD><EFBFBD> (m_bBuffValue)%<25><>ŭ<EFBFBD><C5AD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><20>־<EFBFBD><D6BE><EFBFBD><EFBFBD>Ƿ<EFBFBD>,
// (bNewValue)%<25><>ŭ<EFBFBD><C5AD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
for (TMapAttr::iterator it = m_map_additional_attrs.begin(); it != m_map_additional_attrs.end(); it++)
{
int& sum_of_attr_value = it->second;
int old_value = sum_of_attr_value * m_bBuffValue / 100;
int new_value = sum_of_attr_value * bNewValue / 100;
m_pBuffOwner->ApplyPoint(it->first, -sum_of_attr_value * m_bBuffValue / 100);
}
m_bBuffValue = bNewValue;
}
}
void CBuffOnAttributes::GiveAllAttributes()
{
if (0 == m_bBuffValue)
return;
for (TMapAttr::iterator it = m_map_additional_attrs.begin(); it != m_map_additional_attrs.end(); it++)
{
BYTE apply_type = it->first;
int apply_value = it->second * m_bBuffValue / 100;
m_pBuffOwner->ApplyPoint(apply_type, apply_value);
}
}
bool CBuffOnAttributes::On(BYTE bValue)
{
if (0 != m_bBuffValue || 0 == bValue)
return false;
int n = m_p_vec_buff_wear_targets->size();
m_map_additional_attrs.clear();
for (int i = 0; i < n; i++)
{
LPITEM pItem = m_pBuffOwner->GetWear(m_p_vec_buff_wear_targets->at(i));
if (NULL != pItem)
{
int m = pItem->GetAttributeCount();
for (int j = 0; j < m; j++)
{
TPlayerItemAttribute attr = pItem->GetAttribute(j);
TMapAttr::iterator it = m_map_additional_attrs.find(attr.bType);
if (it != m_map_additional_attrs.end())
{
it->second += attr.sValue;
}
else
{
m_map_additional_attrs.insert(TMapAttr::value_type(attr.bType, attr.sValue));
}
}
}
}
for (TMapAttr::iterator it = m_map_additional_attrs.begin(); it != m_map_additional_attrs.end(); it++)
{
m_pBuffOwner->ApplyPoint(it->first, it->second * bValue / 100);
}
m_bBuffValue = bValue;
return true;
}
void CBuffOnAttributes::Off()
{
if (0 == m_bBuffValue)
return ;
for (TMapAttr::iterator it = m_map_additional_attrs.begin(); it != m_map_additional_attrs.end(); it++)
{
m_pBuffOwner->ApplyPoint(it->first, -it->second * m_bBuffValue / 100);
}
Initialize();
}

View File

@ -0,0 +1,42 @@
#ifndef __METIN2_BUFF_ON_ATTRIBUTES_H
#define __METIN2_BUFF_ON_ATTRIBUTES_H
class CHARACTER;
class CBuffOnAttributes
{
public:
CBuffOnAttributes(LPCHARACTER pOwner, BYTE m_point_type, std::vector <BYTE>* vec_buff_targets);
~CBuffOnAttributes();
// <20><><EFBFBD><EFBFBD> <20><> <20≯鼭, m_p_vec_buff_wear_targets<74><73> <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20>ش<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ȿ<><C8BF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
void RemoveBuffFromItem(LPITEM pItem);
// m_p_vec_buff_wear_targets<74><73> <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20>ش<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> attribute<74><65> <20><><EFBFBD><EFBFBD> ȿ<><C8BF> <20>߰<EFBFBD>.
void AddBuffFromItem(LPITEM pItem);
// m_bBuffValue<75><65> <20>ٲٰ<D9B2>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ٲ<EFBFBD>.
void ChangeBuffValue(BYTE bNewValue);
// CHRACTRE::ComputePoints<74><73><EFBFBD><EFBFBD> <20>Ӽ<EFBFBD>ġ<EFBFBD><C4A1> <20>ʱ<EFBFBD>ȭ<EFBFBD>ϰ<EFBFBD> <20>ٽ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϹǷ<CFB9>,
// <20><><EFBFBD><EFBFBD> <20>Ӽ<EFBFBD>ġ<EFBFBD><C4A1><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> owner<65><72><EFBFBD><EFBFBD> <20><>.
void GiveAllAttributes();
// m_p_vec_buff_wear_targets<74><73> <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> attribute<74><65> type<70><65><EFBFBD><EFBFBD> <20>ջ<EFBFBD><D5BB>ϰ<EFBFBD>,
// <20><> attribute<74><65><EFBFBD><EFBFBD> (m_bBuffValue)% <20><>ŭ<EFBFBD><C5AD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>.
bool On(BYTE bValue);
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>, <20>ʱ<EFBFBD>ȭ
void Off();
void Initialize();
private:
LPCHARACTER m_pBuffOwner;
BYTE m_bPointType;
BYTE m_bBuffValue;
std::vector <BYTE>* m_p_vec_buff_wear_targets;
// apply_type, apply_value <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>
typedef std::map <BYTE, int> TMapAttr;
// m_p_vec_buff_wear_targets<74><73> <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> attribute<74><65> type<70><65><EFBFBD><EFBFBD> <20>ջ<EFBFBD><D5BB>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
TMapAttr m_map_additional_attrs;
};
#endif

View File

@ -0,0 +1,38 @@
#include "stdafx.h"
#include "buffer_manager.h"
TEMP_BUFFER::TEMP_BUFFER(int Size, bool bForceDelete)
{
forceDelete = bForceDelete;
if (forceDelete)
Size = MAX(Size, 1024 * 128);
buf = buffer_new(Size);
}
TEMP_BUFFER::~TEMP_BUFFER()
{
buffer_delete(buf);
}
const void * TEMP_BUFFER::read_peek()
{
return (buffer_read_peek(buf));
}
void TEMP_BUFFER::write(const void * data, int size)
{
buffer_write(buf, data, size);
}
int TEMP_BUFFER::size()
{
return buffer_size(buf);
}
void TEMP_BUFFER::reset()
{
buffer_reset(buf);
}

22
game/src/buffer_manager.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef __INC_METIN_II_GAME_BUFFER_MANAGER_H__
#define __INC_METIN_II_GAME_BUFFER_MANAGER_H__
class TEMP_BUFFER
{
public:
TEMP_BUFFER(int Size = 8192, bool ForceDelete = false );
~TEMP_BUFFER();
const void * read_peek();
void write(const void * data, int size);
int size();
void reset();
LPBUFFER getptr() { return buf; }
protected:
LPBUFFER buf;
bool forceDelete;
};
#endif

View File

@ -0,0 +1,70 @@
#!/usr/local/bin/python
import sys
import glob
def IsHangulInLine(line):
for ch in line:
if ord(ch) >= 128:
return True
return False
hanList = []
for fileName in glob.glob("*.cpp"):
isComment = False
lines = open(fileName).readlines()
for line in lines:
linePos = lines.index(line)
if isComment:
commentEnd = line.find("*/")
if commentEnd < 0:
continue
else:
line = line[commentEnd+2:]
isComment = False
else:
commentBegin = line.find("/*")
if commentBegin >= 0:
commentEnd = line.find("*/")
if commentEnd >= 0:
line = line[:commentBegin] + line[commentEnd+2:]
else:
isComment = True
while True:
pos = line.find("TEXT")
if pos < 0:
break
if len(line) < pos + 5:
break
if line[pos+4] != "(":
break
pos += 5
if line[pos] != '"':
break
endPos = line[pos+1:].find('"')
if endPos < 0:
raise
endPos += pos
endPos += 2
han = line[pos+1:endPos-1]
if not han in hanList:
hanList.append(han)
line = line[endPos:]
out = open("locale_string.txt", "w")
for han in hanList:
out.write("%s\n" % (han))
print han

1269
game/src/building.cpp Normal file

File diff suppressed because it is too large Load Diff

152
game/src/building.h Normal file
View File

@ -0,0 +1,152 @@
#ifndef __INC_METIN_II_BUILDING_H__
#define __INC_METIN_II_BUILDING_H__
#include "../../common/building.h"
namespace building
{
class CLand;
class CObject : public CEntity
{
public:
CObject(TObject * pData, TObjectProto * pProto);
virtual ~CObject();
void Destroy();
virtual void EncodeInsertPacket(LPENTITY entity);
virtual void EncodeRemovePacket(LPENTITY entity);
DWORD GetID() { return m_data.dwID; }
void SetVID(DWORD dwVID);
DWORD GetVID() { return m_dwVID; }
bool Show(long lMapIndex, long x, long y);
void Save();
void SetLand(CLand * pkLand) { m_pkLand = pkLand; }
CLand * GetLand() { return m_pkLand; }
DWORD GetVnum() { return m_pProto ? m_pProto->dwVnum : 0; }
DWORD GetGroup() { return m_pProto ? m_pProto->dwGroupVnum : 0; }
void RegenNPC();
// BUILDING_NPC
void ApplySpecialEffect();
void RemoveSpecialEffect();
void Reconstruct(DWORD dwVnum);
LPCHARACTER GetNPC() { return m_chNPC; }
// END_OF_BUILDING_NPC
protected:
TObjectProto * m_pProto;
TObject m_data;
DWORD m_dwVID;
CLand * m_pkLand;
LPCHARACTER m_chNPC;
};
class CLand
{
public:
CLand(TLand * pData);
~CLand();
void Destroy();
const TLand & GetData();
void PutData(const TLand * data);
DWORD GetID() const { return m_data.dwID; }
void SetOwner(DWORD dwGID);
DWORD GetOwner() const { return m_data.dwGuildID; }
void InsertObject(LPOBJECT pkObj);
LPOBJECT FindObject(DWORD dwID);
LPOBJECT FindObjectByVID(DWORD dwVID);
LPOBJECT FindObjectByVnum(DWORD dwVnum);
LPOBJECT FindObjectByGroup(DWORD dwGroupVnum);
LPOBJECT FindObjectByNPC(LPCHARACTER npc);
void DeleteObject(DWORD dwID);
bool RequestCreateObject(DWORD dwVnum, long lMapIndex, long x, long y, float xRot, float yRot, float zRot, bool checkAnother);
void RequestDeleteObject(DWORD dwID);
void RequestDeleteObjectByVID(DWORD dwVID);
void RequestUpdate(DWORD dwGuild);
// LAND_CLEAR
void ClearLand();
// END_LAND_CLEAR
// BUILD_WALL
bool RequestCreateWall(long nMapIndex, float rot);
void RequestDeleteWall();
bool RequestCreateWallBlocks(DWORD dwVnum, long nMapIndex, char wallSize, bool doorEast, bool doorWest, bool doorSouth, bool doorNorth);
void RequestDeleteWallBlocks(DWORD dwVnum);
// END_BUILD_WALL
DWORD GetMapIndex() { return m_data.lMapIndex; }
protected:
TLand m_data;
std::map<DWORD, LPOBJECT> m_map_pkObject;
std::map<DWORD, LPOBJECT> m_map_pkObjectByVID;
// BUILD_WALL
private :
void DrawWall(DWORD dwVnum, long nMapIndex, long& centerX, long& centerY, char length, float zRot);
// END_BUILD_WALL
};
class CManager : public singleton<CManager>
{
public:
CManager();
virtual ~CManager();
void Destroy();
void FinalizeBoot();
bool LoadObjectProto(const TObjectProto * pProto, int size);
TObjectProto * GetObjectProto(DWORD dwVnum);
bool LoadLand(TLand * pTable);
CLand * FindLand(DWORD dwID);
CLand * FindLand(long lMapIndex, long x, long y);
CLand * FindLandByGuild(DWORD GID);
void UpdateLand(TLand * pTable);
bool LoadObject(TObject * pTable, bool isBoot=false);
void DeleteObject(DWORD dwID);
void UnregisterObject(LPOBJECT pkObj);
LPOBJECT FindObjectByVID(DWORD dwVID);
void SendLandList(LPDESC d, long lMapIndex);
// LAND_CLEAR
void ClearLand(DWORD dwLandID);
void ClearLandByGuildID(DWORD dwGuildID);
// END_LAND_CLEAR
protected:
std::vector<TObjectProto> m_vec_kObjectProto;
std::map<DWORD, TObjectProto *> m_map_pkObjectProto;
std::map<DWORD, CLand *> m_map_pkLand;
std::map<DWORD, LPOBJECT> m_map_pkObjByID;
std::map<DWORD, LPOBJECT> m_map_pkObjByVID;
};
}
#endif

1079
game/src/castle.cpp Normal file

File diff suppressed because it is too large Load Diff

77
game/src/castle.h Normal file
View File

@ -0,0 +1,77 @@
/*********************************************************************
* date : 2007.04.07
* file : castle.h
* author : mhh
* description :
*/
#ifndef _castle_h_
#define _castle_h_
#define MAX_CASTLE_GUARD_REGION 4 // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ġ <20><><EFBFBD><EFBFBD>
#define MAX_CASTLE_GUARD_PER_REGION 10 // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ġ<EFBFBD>Ҽ<EFBFBD><D2BC>ִ<EFBFBD> <20><><EFBFBD>񺴱׷<F1BAB4B1>
#define MAX_CASTLE_FROG 20 // Ȳ<><C8B2> <20>β<EFBFBD><CEB2><EFBFBD>
#define MAX_CASTLE_TOWER 10 // <20><>ȭ <20>ִ<EFBFBD> <20><>ȯ <20><><EFBFBD><EFBFBD>
#define MIN_CASTLE_TOWER 5 // <20><>ȭ <20>ּ<EFBFBD> <20><>ȯ <20><><EFBFBD><EFBFBD>
#define CASTLE_FROG_PRICE 100000000 // Ȳ<>ݵβ<DDB5><CEB2><EFBFBD> <20><><EFBFBD><EFBFBD> (1<><31>)
#define CASTLE_FROG_VNUM 11505 // Ȳ<>ݵβ<DDB5><CEB2><EFBFBD> <20><>ȣ
//#define CASTLE_TOWER_VNUM 11506 // <20><>ȭ <20><>ȣ
#define IS_CASTLE_MAP(map) (181==(map)||182==(map)||(183)==(map))
//#define IS_CASTLE_TOWER(vnum) (11506==(vnum)||11507==(vnum)||11508==(vnum)||11509==(vnum) || 11510==(vnum))
enum CASTLE_STATE
{
CASTLE_SIEGE_NONE, // <20><>ȭ<EFBFBD><C8AD><EFBFBD><EFBFBD>
CASTLE_SIEGE_STRUGGLE, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CASTLE_SIEGE_END // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ߴٸ<DFB4> 1<>ð<EFBFBD><C3B0><EFBFBD><EFBFBD><EFBFBD> <20><>ȭ<EFBFBD><C8AD> <20><> <20><> <20>ִ<EFBFBD>.
};
struct CASTLE_DATA
{
LPCHARACTER frog[MAX_CASTLE_FROG]; // Ȳ<>ݵβ<DDB5><CEB2><EFBFBD>
LPCHARACTER guard[MAX_CASTLE_GUARD_REGION][MAX_CASTLE_GUARD_PER_REGION]; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
DWORD guard_group[MAX_CASTLE_GUARD_REGION][MAX_CASTLE_GUARD_PER_REGION]; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
LPCHARACTER tower[MAX_CASTLE_TOWER]; // <20><>ȭ
LPEVENT siege_event;
LPEVENT stone_event;
};
/* extern functions */
bool castle_boot();
void castle_save();
int castle_siege(int empire, int tower_count);
void castle_start_siege(int empire, int tower_count);
void castle_end_siege();
LPCHARACTER castle_spawn_frog(int empire);
LPCHARACTER castle_spawn_guard(int empire, DWORD group_vnum, int region_index);
bool castle_spawn_tower(int empire, int tower_count);
void castle_guard_die(LPCHARACTER ch, LPCHARACTER killer);
void castle_frog_die(LPCHARACTER ch, LPCHARACTER killer);
void castle_tower_die(LPCHARACTER ch, LPCHARACTER killer);
int castle_guard_count(int empire, int region_index);
int castle_frog_count(int empire);
bool castle_is_guard_vnum(DWORD vnum);
int castle_cost_of_hiring_guard(DWORD vnum);
bool castle_can_attack(LPCHARACTER ch, LPCHARACTER victim);
bool castle_frog_to_empire_money(LPCHARACTER ch);
bool castle_is_my_castle(int empire, int map_index);
bool castle_is_tower_vnum(DWORD vnum);
#endif /* _castle_h_ */

7225
game/src/char.cpp Normal file

File diff suppressed because it is too large Load Diff

2054
game/src/char.h Normal file

File diff suppressed because it is too large Load Diff

837
game/src/char_affect.cpp Normal file
View File

@ -0,0 +1,837 @@
#include "stdafx.h"
#include "config.h"
#include "char.h"
#include "char_manager.h"
#include "affect.h"
#include "packet.h"
#include "buffer_manager.h"
#include "desc_client.h"
#include "battle.h"
#include "guild.h"
#include "utils.h"
#include "locale_service.h"
#include "lua_incl.h"
#include "arena.h"
#include "horsename_manager.h"
#include "item.h"
#include "DragonSoul.h"
#define IS_NO_SAVE_AFFECT(type) ((type) == AFFECT_WAR_FLAG || (type) == AFFECT_REVIVE_INVISIBLE || ((type) >= AFFECT_PREMIUM_START && (type) <= AFFECT_PREMIUM_END))
#define IS_NO_CLEAR_ON_DEATH_AFFECT(type) ((type) == AFFECT_BLOCK_CHAT || ((type) >= 500 && (type) < 600))
void SendAffectRemovePacket(LPDESC d, DWORD pid, DWORD type, BYTE point)
{
TPacketGCAffectRemove ptoc;
ptoc.bHeader = HEADER_GC_AFFECT_REMOVE;
ptoc.dwType = type;
ptoc.bApplyOn = point;
d->Packet(&ptoc, sizeof(TPacketGCAffectRemove));
TPacketGDRemoveAffect ptod;
ptod.dwPID = pid;
ptod.dwType = type;
ptod.bApplyOn = point;
db_clientdesc->DBPacket(HEADER_GD_REMOVE_AFFECT, 0, &ptod, sizeof(ptod));
}
void SendAffectAddPacket(LPDESC d, CAffect * pkAff)
{
TPacketGCAffectAdd ptoc;
ptoc.bHeader = HEADER_GC_AFFECT_ADD;
ptoc.elem.dwType = pkAff->dwType;
ptoc.elem.bApplyOn = pkAff->bApplyOn;
ptoc.elem.lApplyValue = pkAff->lApplyValue;
ptoc.elem.dwFlag = pkAff->dwFlag;
ptoc.elem.lDuration = pkAff->lDuration;
ptoc.elem.lSPCost = pkAff->lSPCost;
d->Packet(&ptoc, sizeof(TPacketGCAffectAdd));
}
////////////////////////////////////////////////////////////////////
// Affect
CAffect * CHARACTER::FindAffect(DWORD dwType, BYTE bApply) const
{
itertype(m_list_pkAffect) it = m_list_pkAffect.begin();
while (it != m_list_pkAffect.end())
{
CAffect * pkAffect = *it++;
if (pkAffect->dwType == dwType && (bApply == APPLY_NONE || bApply == pkAffect->bApplyOn))
return pkAffect;
}
return NULL;
}
EVENTFUNC(affect_event)
{
char_event_info* info = dynamic_cast<char_event_info*>( event->info );
if ( info == NULL )
{
sys_err( "affect_event> <Factor> Null pointer" );
return 0;
}
LPCHARACTER ch = info->ch;
if (ch == NULL) { // <Factor>
return 0;
}
if (!ch->UpdateAffect())
return 0;
else
return passes_per_sec; // 1<><31>
}
bool CHARACTER::UpdateAffect()
{
// affect_event <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ƴ<EFBFBD><C6B4><EFBFBD><EFBFBD><EFBFBD>, 1<><31>¥<EFBFBD><C2A5> <20>̺<EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD>
// <20>̰<EFBFBD> <20><><EFBFBD>̶<EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
if (GetPoint(POINT_HP_RECOVERY) > 0)
{
if (GetMaxHP() <= GetHP())
{
PointChange(POINT_HP_RECOVERY, -GetPoint(POINT_HP_RECOVERY));
}
else
{
int iVal = 0;
if (LC_IsYMIR())
{
iVal = MIN(GetPoint(POINT_HP_RECOVERY), GetMaxHP() * 9 / 100);
}
else
{
iVal = MIN(GetPoint(POINT_HP_RECOVERY), GetMaxHP() * 7 / 100);
}
PointChange(POINT_HP, iVal);
PointChange(POINT_HP_RECOVERY, -iVal);
}
}
if (GetPoint(POINT_SP_RECOVERY) > 0)
{
if (GetMaxSP() <= GetSP())
PointChange(POINT_SP_RECOVERY, -GetPoint(POINT_SP_RECOVERY));
else
{
int iVal;
if (!g_iUseLocale)
iVal = MIN(GetPoint(POINT_SP_RECOVERY), GetMaxSP() * 7 / 100);
else
iVal = MIN(GetPoint(POINT_SP_RECOVERY), GetMaxSP() * 7 / 100);
PointChange(POINT_SP, iVal);
PointChange(POINT_SP_RECOVERY, -iVal);
}
}
if (GetPoint(POINT_HP_RECOVER_CONTINUE) > 0)
{
PointChange(POINT_HP, GetPoint(POINT_HP_RECOVER_CONTINUE));
}
if (GetPoint(POINT_SP_RECOVER_CONTINUE) > 0)
{
PointChange(POINT_SP, GetPoint(POINT_SP_RECOVER_CONTINUE));
}
AutoRecoveryItemProcess( AFFECT_AUTO_HP_RECOVERY );
AutoRecoveryItemProcess( AFFECT_AUTO_SP_RECOVERY );
// <20><><EFBFBD>׹̳<D7B9> ȸ<><C8B8>
if (GetMaxStamina() > GetStamina())
{
int iSec = (get_dword_time() - GetStopTime()) / 3000;
if (iSec)
PointChange(POINT_STAMINA, GetMaxStamina()/1);
}
// ProcessAffect<63><74> affect<63><74> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> true<75><65> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
if (ProcessAffect())
if (GetPoint(POINT_HP_RECOVERY) == 0 && GetPoint(POINT_SP_RECOVERY) == 0 && GetStamina() == GetMaxStamina())
{
m_pkAffectEvent = NULL;
return false;
}
return true;
}
void CHARACTER::StartAffectEvent()
{
if (m_pkAffectEvent)
return;
char_event_info* info = AllocEventInfo<char_event_info>();
info->ch = this;
m_pkAffectEvent = event_create(affect_event, info, passes_per_sec);
sys_log(1, "StartAffectEvent %s %p %p", GetName(), this, get_pointer(m_pkAffectEvent));
}
void CHARACTER::ClearAffect(bool bSave)
{
TAffectFlag afOld = m_afAffectFlag;
WORD wMovSpd = GetPoint(POINT_MOV_SPEED);
WORD wAttSpd = GetPoint(POINT_ATT_SPEED);
itertype(m_list_pkAffect) it = m_list_pkAffect.begin();
while (it != m_list_pkAffect.end())
{
CAffect * pkAff = *it;
if (bSave)
{
if ( IS_NO_CLEAR_ON_DEATH_AFFECT(pkAff->dwType) || IS_NO_SAVE_AFFECT(pkAff->dwType) )
{
++it;
continue;
}
if (IsPC())
{
SendAffectRemovePacket(GetDesc(), GetPlayerID(), pkAff->dwType, pkAff->bApplyOn);
}
}
ComputeAffect(pkAff, false);
it = m_list_pkAffect.erase(it);
CAffect::Release(pkAff);
}
if (afOld != m_afAffectFlag ||
wMovSpd != GetPoint(POINT_MOV_SPEED) ||
wAttSpd != GetPoint(POINT_ATT_SPEED))
UpdatePacket();
CheckMaximumPoints();
if (m_list_pkAffect.empty())
event_cancel(&m_pkAffectEvent);
}
int CHARACTER::ProcessAffect()
{
bool bDiff = false;
CAffect *pkAff = NULL;
//
// <20><><EFBFBD><EFBFBD><EFBFBD>̾<EFBFBD> ó<><C3B3>
//
for (int i = 0; i <= PREMIUM_MAX_NUM; ++i)
{
int aff_idx = i + AFFECT_PREMIUM_START;
pkAff = FindAffect(aff_idx);
if (!pkAff)
continue;
int remain = GetPremiumRemainSeconds(i);
if (remain < 0)
{
RemoveAffect(aff_idx);
bDiff = true;
}
else
pkAff->lDuration = remain + 1;
}
////////// HAIR_AFFECT
pkAff = FindAffect(AFFECT_HAIR);
if (pkAff)
{
// IF HAIR_LIMIT_TIME() < CURRENT_TIME()
if ( this->GetQuestFlag("hair.limit_time") < get_global_time())
{
// SET HAIR NORMAL
this->SetPart(PART_HAIR, 0);
// REMOVE HAIR AFFECT
RemoveAffect(AFFECT_HAIR);
}
else
{
// INCREASE AFFECT DURATION
++(pkAff->lDuration);
}
}
////////// HAIR_AFFECT
//
CHorseNameManager::instance().Validate(this);
TAffectFlag afOld = m_afAffectFlag;
long lMovSpd = GetPoint(POINT_MOV_SPEED);
long lAttSpd = GetPoint(POINT_ATT_SPEED);
itertype(m_list_pkAffect) it;
it = m_list_pkAffect.begin();
while (it != m_list_pkAffect.end())
{
pkAff = *it;
bool bEnd = false;
if (pkAff->dwType >= GUILD_SKILL_START && pkAff->dwType <= GUILD_SKILL_END)
{
if (!GetGuild() || !GetGuild()->UnderAnyWar())
bEnd = true;
}
if (pkAff->lSPCost > 0)
{
if (GetSP() < pkAff->lSPCost)
bEnd = true;
else
PointChange(POINT_SP, -pkAff->lSPCost);
}
// AFFECT_DURATION_BUG_FIX
// <20><><EFBFBD><EFBFBD> ȿ<><C8BF> <20><><EFBFBD><EFBFBD><EFBFBD>۵<EFBFBD> <20>ð<EFBFBD><C3B0><EFBFBD> <20><><EFBFBD>δ<EFBFBD>.
// <20>ð<EFBFBD><C3B0><EFBFBD> <20>ſ<EFBFBD> ũ<><C5A9> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>̶<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
if ( --pkAff->lDuration <= 0 )
{
bEnd = true;
}
// END_AFFECT_DURATION_BUG_FIX
if (bEnd)
{
it = m_list_pkAffect.erase(it);
ComputeAffect(pkAff, false);
bDiff = true;
if (IsPC())
{
SendAffectRemovePacket(GetDesc(), GetPlayerID(), pkAff->dwType, pkAff->bApplyOn);
}
CAffect::Release(pkAff);
continue;
}
++it;
}
if (bDiff)
{
if (afOld != m_afAffectFlag ||
lMovSpd != GetPoint(POINT_MOV_SPEED) ||
lAttSpd != GetPoint(POINT_ATT_SPEED))
{
UpdatePacket();
}
CheckMaximumPoints();
}
if (m_list_pkAffect.empty())
return true;
return false;
}
void CHARACTER::SaveAffect()
{
TPacketGDAddAffect p;
itertype(m_list_pkAffect) it = m_list_pkAffect.begin();
while (it != m_list_pkAffect.end())
{
CAffect * pkAff = *it++;
if (IS_NO_SAVE_AFFECT(pkAff->dwType))
continue;
sys_log(1, "AFFECT_SAVE: %u %u %d %d", pkAff->dwType, pkAff->bApplyOn, pkAff->lApplyValue, pkAff->lDuration);
p.dwPID = GetPlayerID();
p.elem.dwType = pkAff->dwType;
p.elem.bApplyOn = pkAff->bApplyOn;
p.elem.lApplyValue = pkAff->lApplyValue;
p.elem.dwFlag = pkAff->dwFlag;
p.elem.lDuration = pkAff->lDuration;
p.elem.lSPCost = pkAff->lSPCost;
db_clientdesc->DBPacket(HEADER_GD_ADD_AFFECT, 0, &p, sizeof(p));
}
}
EVENTINFO(load_affect_login_event_info)
{
DWORD pid;
DWORD count;
char* data;
load_affect_login_event_info()
: pid( 0 )
, count( 0 )
, data( 0 )
{
}
};
EVENTFUNC(load_affect_login_event)
{
load_affect_login_event_info* info = dynamic_cast<load_affect_login_event_info*>( event->info );
if ( info == NULL )
{
sys_err( "load_affect_login_event_info> <Factor> Null pointer" );
return 0;
}
DWORD dwPID = info->pid;
LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(dwPID);
if (!ch)
{
M2_DELETE_ARRAY(info->data);
return 0;
}
LPDESC d = ch->GetDesc();
if (!d)
{
M2_DELETE_ARRAY(info->data);
return 0;
}
if (d->IsPhase(PHASE_HANDSHAKE) ||
d->IsPhase(PHASE_LOGIN) ||
d->IsPhase(PHASE_SELECT) ||
d->IsPhase(PHASE_DEAD) ||
d->IsPhase(PHASE_LOADING))
{
return PASSES_PER_SEC(1);
}
else if (d->IsPhase(PHASE_CLOSE))
{
M2_DELETE_ARRAY(info->data);
return 0;
}
else if (d->IsPhase(PHASE_GAME))
{
sys_log(1, "Affect Load by Event");
ch->LoadAffect(info->count, (TPacketAffectElement*)info->data);
M2_DELETE_ARRAY(info->data);
return 0;
}
else
{
sys_err("input_db.cpp:quest_login_event INVALID PHASE pid %d", ch->GetPlayerID());
M2_DELETE_ARRAY(info->data);
return 0;
}
}
void CHARACTER::LoadAffect(DWORD dwCount, TPacketAffectElement * pElements)
{
m_bIsLoadedAffect = false;
if (!GetDesc()->IsPhase(PHASE_GAME))
{
if (test_server)
sys_log(0, "LOAD_AFFECT: Creating Event", GetName(), dwCount);
load_affect_login_event_info* info = AllocEventInfo<load_affect_login_event_info>();
info->pid = GetPlayerID();
info->count = dwCount;
info->data = M2_NEW char[sizeof(TPacketAffectElement) * dwCount];
thecore_memcpy(info->data, pElements, sizeof(TPacketAffectElement) * dwCount);
event_create(load_affect_login_event, info, PASSES_PER_SEC(1));
return;
}
ClearAffect(true);
if (test_server)
sys_log(0, "LOAD_AFFECT: %s count %d", GetName(), dwCount);
TAffectFlag afOld = m_afAffectFlag;
long lMovSpd = GetPoint(POINT_MOV_SPEED);
long lAttSpd = GetPoint(POINT_ATT_SPEED);
for (DWORD i = 0; i < dwCount; ++i, ++pElements)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʴ´<CAB4>.
if (pElements->dwType == SKILL_MUYEONG)
continue;
if (AFFECT_AUTO_HP_RECOVERY == pElements->dwType || AFFECT_AUTO_SP_RECOVERY == pElements->dwType)
{
LPITEM item = FindItemByID( pElements->dwFlag );
if (NULL == item)
continue;
item->Lock(true);
}
if (pElements->bApplyOn >= POINT_MAX_NUM)
{
sys_err("invalid affect data %s ApplyOn %u ApplyValue %d",
GetName(), pElements->bApplyOn, pElements->lApplyValue);
continue;
}
if (test_server)
{
sys_log(0, "Load Affect : Affect %s %d %d", GetName(), pElements->dwType, pElements->bApplyOn );
}
CAffect* pkAff = CAffect::Acquire();
m_list_pkAffect.push_back(pkAff);
pkAff->dwType = pElements->dwType;
pkAff->bApplyOn = pElements->bApplyOn;
pkAff->lApplyValue = pElements->lApplyValue;
pkAff->dwFlag = pElements->dwFlag;
pkAff->lDuration = pElements->lDuration;
pkAff->lSPCost = pElements->lSPCost;
SendAffectAddPacket(GetDesc(), pkAff);
ComputeAffect(pkAff, true);
}
if ( CArenaManager::instance().IsArenaMap(GetMapIndex()) == true )
{
RemoveGoodAffect();
}
if (afOld != m_afAffectFlag || lMovSpd != GetPoint(POINT_MOV_SPEED) || lAttSpd != GetPoint(POINT_ATT_SPEED))
{
UpdatePacket();
}
StartAffectEvent();
m_bIsLoadedAffect = true;
// <20><>ȥ<EFBFBD><C8A5> <20><><EFBFBD><EFBFBD> <20>ε<EFBFBD> <20><> <20>ʱ<EFBFBD>ȭ
DragonSoul_Initialize();
}
bool CHARACTER::AddAffect(DWORD dwType, BYTE bApplyOn, long lApplyValue, DWORD dwFlag, long lDuration, long lSPCost, bool bOverride, bool IsCube )
{
// CHAT_BLOCK
if (dwType == AFFECT_BLOCK_CHAT && lDuration > 1)
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ä<><C3A4><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
}
// END_OF_CHAT_BLOCK
if (lDuration == 0)
{
sys_err("Character::AddAffect lDuration == 0 type %d", lDuration, dwType);
lDuration = 1;
}
CAffect * pkAff = NULL;
if (IsCube)
pkAff = FindAffect(dwType,bApplyOn);
else
pkAff = FindAffect(dwType);
if (dwFlag == AFF_STUN)
{
if (m_posDest.x != GetX() || m_posDest.y != GetY())
{
m_posDest.x = m_posStart.x = GetX();
m_posDest.y = m_posStart.y = GetY();
battle_end(this);
SyncPacket();
}
}
// <20>̹<EFBFBD> <20>ִ<EFBFBD> ȿ<><C8BF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3>
if (pkAff && bOverride)
{
ComputeAffect(pkAff, false); // <20>ϴ<EFBFBD> ȿ<><C8BF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD>
if (GetDesc())
SendAffectRemovePacket(GetDesc(), GetPlayerID(), pkAff->dwType, pkAff->bApplyOn);
}
else
{
//
// <20><> <20><><EFBFBD><20>߰<EFBFBD>
//
// NOTE: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> type <20><><EFBFBD>ε<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD>.
//
pkAff = CAffect::Acquire();
m_list_pkAffect.push_back(pkAff);
}
sys_log(1, "AddAffect %s type %d apply %d %d flag %u duration %d", GetName(), dwType, bApplyOn, lApplyValue, dwFlag, lDuration);
sys_log(0, "AddAffect %s type %d apply %d %d flag %u duration %d", GetName(), dwType, bApplyOn, lApplyValue, dwFlag, lDuration);
pkAff->dwType = dwType;
pkAff->bApplyOn = bApplyOn;
pkAff->lApplyValue = lApplyValue;
pkAff->dwFlag = dwFlag;
pkAff->lDuration = lDuration;
pkAff->lSPCost = lSPCost;
WORD wMovSpd = GetPoint(POINT_MOV_SPEED);
WORD wAttSpd = GetPoint(POINT_ATT_SPEED);
ComputeAffect(pkAff, true);
if (pkAff->dwFlag || wMovSpd != GetPoint(POINT_MOV_SPEED) || wAttSpd != GetPoint(POINT_ATT_SPEED))
UpdatePacket();
StartAffectEvent();
if (IsPC())
{
SendAffectAddPacket(GetDesc(), pkAff);
if (IS_NO_SAVE_AFFECT(pkAff->dwType))
return true;
TPacketGDAddAffect p;
p.dwPID = GetPlayerID();
p.elem.dwType = pkAff->dwType;
p.elem.bApplyOn = pkAff->bApplyOn;
p.elem.lApplyValue = pkAff->lApplyValue;
p.elem.dwFlag = pkAff->dwFlag;
p.elem.lDuration = pkAff->lDuration;
p.elem.lSPCost = pkAff->lSPCost;
db_clientdesc->DBPacket(HEADER_GD_ADD_AFFECT, 0, &p, sizeof(p));
}
return true;
}
void CHARACTER::RefreshAffect()
{
itertype(m_list_pkAffect) it = m_list_pkAffect.begin();
while (it != m_list_pkAffect.end())
{
CAffect * pkAff = *it++;
ComputeAffect(pkAff, true);
}
}
void CHARACTER::ComputeAffect(CAffect * pkAff, bool bAdd)
{
if (bAdd && pkAff->dwType >= GUILD_SKILL_START && pkAff->dwType <= GUILD_SKILL_END)
{
if (!GetGuild())
return;
if (!GetGuild()->UnderAnyWar())
return;
}
if (pkAff->dwFlag)
{
if (!bAdd)
m_afAffectFlag.Reset(pkAff->dwFlag);
else
m_afAffectFlag.Set(pkAff->dwFlag);
}
if (bAdd)
PointChange(pkAff->bApplyOn, pkAff->lApplyValue);
else
PointChange(pkAff->bApplyOn, -pkAff->lApplyValue);
if (pkAff->dwType == SKILL_MUYEONG)
{
if (bAdd)
StartMuyeongEvent();
else
StopMuyeongEvent();
}
}
bool CHARACTER::RemoveAffect(CAffect * pkAff)
{
if (!pkAff)
return false;
// AFFECT_BUF_FIX
m_list_pkAffect.remove(pkAff);
// END_OF_AFFECT_BUF_FIX
ComputeAffect(pkAff, false);
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>״<EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ų <20><><EFBFBD><EFBFBD>-><3E>а<EFBFBD>-><3E><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>(AFFECT_REVIVE_INVISIBLE) <20><> <20>ٷ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><20>߻<EFBFBD><DFBB>Ѵ<EFBFBD>.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>а<EFBFBD><D0B0><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20><>ų ȿ<><C8BF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20>а<EFBFBD> ȿ<><C8BF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD> <20>Ǿ<EFBFBD><C7BE>ִµ<D6B4>,
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20>ٷ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD> RemoveAffect<63><74> <20>Ҹ<EFBFBD><D2B8><EFBFBD> <20>ǰ<EFBFBD>, ComputePoints<74>ϸ鼭 <20>а<EFBFBD> ȿ<><C8BF> + <20><><EFBFBD><EFBFBD> <20><>ų ȿ<><C8BF><EFBFBD><EFBFBD> <20>ȴ<EFBFBD>.
// ComputePoints<74><73><EFBFBD><EFBFBD> <20>а<EFBFBD> <20><><EFBFBD>¸<EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ų ȿ<><C8BF> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ϸ<EFBFBD> <20>DZ<EFBFBD> <20>ϴµ<CFB4>,
// ComputePoints<74><73> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD> <20>־ ū <20><>ȭ<EFBFBD><C8AD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.(<28> side effect<63><74> <20>߻<EFBFBD><DFBB><EFBFBD><EFBFBD><EFBFBD> <20>˱<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.)
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> AFFECT_REVIVE_INVISIBLE<4C><45> RemoveAffect<63><74> <20><><EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
// <20>ð<EFBFBD><C3B0><EFBFBD> <20><> <20>Ǿ<EFBFBD> <20><><EFBFBD><EFBFBD> ȿ<><C8BF><EFBFBD><EFBFBD> Ǯ<><C7AE><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>װ<EFBFBD> <20>߻<EFBFBD><DFBB><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD> <20>׿<EFBFBD> <20>Ȱ<EFBFBD><C8B0><EFBFBD> <20><>.
// (ProcessAffect<63><74> <20><><EFBFBD><EFBFBD> <20>ð<EFBFBD><C3B0><EFBFBD> <20><> <20>Ǿ Affect<63><74> <20><><EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD> <20><><EFBFBD><EFBFBD>, ComputePoints<74><73> <20>θ<EFBFBD><CEB8><EFBFBD> <20>ʴ´<CAB4>.)
if (AFFECT_REVIVE_INVISIBLE != pkAff->dwType)
{
ComputePoints();
}
CheckMaximumPoints();
if (test_server)
sys_log(0, "AFFECT_REMOVE: %s (flag %u apply: %u)", GetName(), pkAff->dwFlag, pkAff->bApplyOn);
if (IsPC())
{
SendAffectRemovePacket(GetDesc(), GetPlayerID(), pkAff->dwType, pkAff->bApplyOn);
}
CAffect::Release(pkAff);
return true;
}
bool CHARACTER::RemoveAffect(DWORD dwType)
{
// CHAT_BLOCK
if (dwType == AFFECT_BLOCK_CHAT)
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ä<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ǯ<>Ƚ<EFBFBD><C8BD>ϴ<EFBFBD>."));
}
// END_OF_CHAT_BLOCK
bool flag = false;
CAffect * pkAff;
while ((pkAff = FindAffect(dwType)))
{
RemoveAffect(pkAff);
flag = true;
}
return flag;
}
bool CHARACTER::IsAffectFlag(DWORD dwAff) const
{
return m_afAffectFlag.IsSet(dwAff);
}
void CHARACTER::RemoveGoodAffect()
{
RemoveAffect(AFFECT_MOV_SPEED);
RemoveAffect(AFFECT_ATT_SPEED);
RemoveAffect(AFFECT_STR);
RemoveAffect(AFFECT_DEX);
RemoveAffect(AFFECT_INT);
RemoveAffect(AFFECT_CON);
RemoveAffect(AFFECT_CHINA_FIREWORK);
RemoveAffect(SKILL_JEONGWI);
RemoveAffect(SKILL_GEOMKYUNG);
RemoveAffect(SKILL_CHUNKEON);
RemoveAffect(SKILL_EUNHYUNG);
RemoveAffect(SKILL_GYEONGGONG);
RemoveAffect(SKILL_GWIGEOM);
RemoveAffect(SKILL_TERROR);
RemoveAffect(SKILL_JUMAGAP);
RemoveAffect(SKILL_MANASHILED);
RemoveAffect(SKILL_HOSIN);
RemoveAffect(SKILL_REFLECT);
RemoveAffect(SKILL_KWAESOK);
RemoveAffect(SKILL_JEUNGRYEOK);
RemoveAffect(SKILL_GICHEON);
}
bool CHARACTER::IsGoodAffect(BYTE bAffectType) const
{
switch (bAffectType)
{
case (AFFECT_MOV_SPEED):
case (AFFECT_ATT_SPEED):
case (AFFECT_STR):
case (AFFECT_DEX):
case (AFFECT_INT):
case (AFFECT_CON):
case (AFFECT_CHINA_FIREWORK):
case (SKILL_JEONGWI):
case (SKILL_GEOMKYUNG):
case (SKILL_CHUNKEON):
case (SKILL_EUNHYUNG):
case (SKILL_GYEONGGONG):
case (SKILL_GWIGEOM):
case (SKILL_TERROR):
case (SKILL_JUMAGAP):
case (SKILL_MANASHILED):
case (SKILL_HOSIN):
case (SKILL_REFLECT):
case (SKILL_KWAESOK):
case (SKILL_JEUNGRYEOK):
case (SKILL_GICHEON):
return true;
}
return false;
}
void CHARACTER::RemoveBadAffect()
{
sys_log(0, "RemoveBadAffect %s", GetName());
// <20><>
RemovePoison();
RemoveFire();
// <20><><EFBFBD><EFBFBD> : Value%<25><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 5<>ʰ<EFBFBD> <20>Ӹ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ư<EFBFBD><C6B0><EFBFBD>. (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1/2 Ȯ<><C8AE><EFBFBD><EFBFBD> Ǯ<><C7AE>) AFF_STUN
RemoveAffect(AFFECT_STUN);
// <20><><EFBFBD>ο<EFBFBD> : Value%<25><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>/<2F>̼<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD>õ<EFBFBD><C3B5><EFBFBD> <20><><EFBFBD><EFBFBD> <20>޶<EFBFBD><DEB6><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD>쿡 AFF_SLOW
RemoveAffect(AFFECT_SLOW);
// <20><><EFBFBD>Ӹ<EFBFBD><D3B8><EFBFBD>
RemoveAffect(SKILL_TUSOK);
// <20><><EFBFBD><EFBFBD>
//RemoveAffect(SKILL_CURSE);
// <20>Ĺ<EFBFBD><C4B9><EFBFBD>
//RemoveAffect(SKILL_PABUP);
// <20><><EFBFBD><EFBFBD> : Value%<25><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ų<EFBFBD><C5B2>. 2<><32> AFF_FAINT
//RemoveAffect(AFFECT_FAINT);
// <20>ٸ<EFBFBD><D9B8><EFBFBD><EFBFBD><EFBFBD> : Value%<25><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>̵<EFBFBD><CCB5>ӵ<EFBFBD><D3B5><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD>. 5<>ʰ<EFBFBD> -40 AFF_WEB
//RemoveAffect(AFFECT_WEB);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> : Value%<25><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 10<31>ʰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ǯ<><C7AE>) AFF_SLEEP
//RemoveAffect(AFFECT_SLEEP);
// <20><><EFBFBD><EFBFBD> : Value%<25><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD>. <20><><EFBFBD>õ<EFBFBD><C3B5><EFBFBD> <20><><EFBFBD><EFBFBD> <20>޶<EFBFBD><DEB6><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD>쿡 AFF_CURSE
//RemoveAffect(AFFECT_CURSE);
// <20><><EFBFBD><EFBFBD> : Value%<25><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 4<>ʰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ų<EFBFBD><C5B2>. AFF_PARA
//RemoveAffect(AFFECT_PARALYZE);
// <20>ε<EFBFBD><CEB5>ں<EFBFBD> : <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
//RemoveAffect(SKILL_BUDONG);
}

3648
game/src/char_battle.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,210 @@
#include "stdafx.h"
#include "config.h"
#include "char.h"
#include "char_manager.h"
#include "db.h"
#include "guild_manager.h"
#include "marriage.h"
/*
Return Value
0 : <20><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> or <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
1 : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٲٷ<D9B2><D9B7><EFBFBD><EFBFBD><EFBFBD>
2 : <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ij<><C4B3><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD>
3 : <20><>ȥ<EFBFBD><C8A5> ij<><C4B3><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD>
999 : <20><><EFBFBD><EFBFBD> <20>̵<EFBFBD> <20><><EFBFBD><EFBFBD>
*/
int CHARACTER::ChangeEmpire(BYTE empire)
{
if (GetEmpire() == empire)
return 1;
char szQuery[1024+1];
DWORD dwAID;
DWORD dwPID[4];
memset(dwPID, 0, sizeof(dwPID));
{
// 1. <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> pid<69><64> <20><><EFBFBD><EFBFBD> <20>´<EFBFBD>
snprintf(szQuery, sizeof(szQuery),
"SELECT id, pid1, pid2, pid3, pid4 FROM player_index%s WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u AND empire=%u",
get_table_postfix(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire());
std::auto_ptr<SQLMsg> msg(DBManager::instance().DirectQuery(szQuery));
if (msg->Get()->uiNumRows == 0)
{
return 0;
}
MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult);
str_to_number(dwAID, row[0]);
str_to_number(dwPID[0], row[1]);
str_to_number(dwPID[1], row[2]);
str_to_number(dwPID[2], row[3]);
str_to_number(dwPID[3], row[4]);
}
const int loop = 4;
{
// 2. <20><> ij<><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>.
// <20><> ij<><C4B3><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD> <20>Ǿ<EFBFBD> <20>ִٸ<D6B4>, <20><><EFBFBD><EFBFBD> <20>̵<EFBFBD><CCB5><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD>.
DWORD dwGuildID[4];
CGuild * pGuild[4];
SQLMsg * pMsg = NULL;
for (int i = 0; i < loop; ++i)
{
snprintf(szQuery, sizeof(szQuery), "SELECT guild_id FROM guild_member%s WHERE pid=%u", get_table_postfix(), dwPID[i]);
pMsg = DBManager::instance().DirectQuery(szQuery);
if (pMsg != NULL)
{
if (pMsg->Get()->uiNumRows > 0)
{
MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
str_to_number(dwGuildID[i], row[0]);
pGuild[i] = CGuildManager::instance().FindGuild(dwGuildID[i]);
if (pGuild[i] != NULL)
{
M2_DELETE(pMsg);
return 2;
}
}
else
{
dwGuildID[i] = 0;
pGuild[i] = NULL;
}
M2_DELETE(pMsg);
}
}
}
{
// 3. <20><> ij<><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȥ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>.
// <20><> ij<><C4B3><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD> <20><>ȥ <20><><EFBFBD><EFBFBD><C2B6><EFBFBD> <20><><EFBFBD><EFBFBD> <20>̵<EFBFBD><CCB5><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD>.
for (int i = 0; i < loop; ++i)
{
if (marriage::CManager::instance().IsEngagedOrMarried(dwPID[i]) == true)
return 3;
}
}
{
// 4. db<64><62> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ <20>Ѵ<EFBFBD>.
snprintf(szQuery, sizeof(szQuery), "UPDATE player_index%s SET empire=%u WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u AND empire=%u",
get_table_postfix(), empire, GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire());
std::auto_ptr<SQLMsg> msg(DBManager::instance().DirectQuery(szQuery));
if (msg->Get()->uiAffectedRows > 0)
{
// 5. <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>̷<EFBFBD><CCB7><EFBFBD> <20>߰<EFBFBD><DFB0>Ѵ<EFBFBD>.
SetChangeEmpireCount();
return 999;
}
}
return 0;
}
int CHARACTER::GetChangeEmpireCount() const
{
char szQuery[1024+1];
DWORD dwAID = GetAID();
if (dwAID == 0)
return 0;
snprintf(szQuery, sizeof(szQuery), "SELECT change_count FROM change_empire WHERE account_id = %u", dwAID);
SQLMsg * pMsg = DBManager::instance().DirectQuery(szQuery);
if (pMsg != NULL)
{
if (pMsg->Get()->uiNumRows == 0)
{
M2_DELETE(pMsg);
return 0;
}
MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
DWORD count = 0;
str_to_number(count, row[0]);
M2_DELETE(pMsg);
return count;
}
return 0;
}
void CHARACTER::SetChangeEmpireCount()
{
char szQuery[1024+1];
DWORD dwAID = GetAID();
if (dwAID == 0) return;
int count = GetChangeEmpireCount();
if (count == 0)
{
count++;
snprintf(szQuery, sizeof(szQuery), "INSERT INTO change_empire VALUES(%u, %d, NOW())", dwAID, count);
}
else
{
count++;
snprintf(szQuery, sizeof(szQuery), "UPDATE change_empire SET change_count=%d WHERE account_id=%u", count, dwAID);
}
std::auto_ptr<SQLMsg> pmsg(DBManager::instance().DirectQuery(szQuery));
}
DWORD CHARACTER::GetAID() const
{
char szQuery[1024+1];
DWORD dwAID = 0;
snprintf(szQuery, sizeof(szQuery), "SELECT id FROM player_index%s WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u AND empire=%u",
get_table_postfix(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire());
SQLMsg* pMsg = DBManager::instance().DirectQuery(szQuery);
if (pMsg != NULL)
{
if (pMsg->Get()->uiNumRows == 0)
{
M2_DELETE(pMsg);
return 0;
}
MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
str_to_number(dwAID, row[0]);
M2_DELETE(pMsg);
return dwAID;
}
else
{
return 0;
}
}

View File

@ -0,0 +1,143 @@
#include "stdafx.h"
#include "char.h"
#include "item.h"
#include "desc.h"
#include "DragonSoul.h"
#include "log.h"
// <20><>ȥ<EFBFBD><C8A5> <20>ʱ<EFBFBD>ȭ
// <20><>ȥ<EFBFBD><C8A5> on/off<66><66> Affect<63><74> <20><><EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,
// <20><>ȥ<EFBFBD><C8A5> Affect<63><74> <20>ִٸ<D6B4> <20><><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD> activate<74>ؾ<EFBFBD><D8BE>Ѵ<EFBFBD>.
// <20><><EFBFBD><EFBFBD> <20><>ȥ<EFBFBD><C8A5> <20><><EFBFBD><EFBFBD> <20>ڰ<EFBFBD><DAB0><EFBFBD> QuestFlag<61><67> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ұ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,
// <20><><EFBFBD><EFBFBD>Ʈ Flag<61><67><EFBFBD><EFBFBD> <20><>ȥ<EFBFBD><C8A5> <20><><EFBFBD><EFBFBD> <20>ڰ<EFBFBD><DAB0><EFBFBD> <20>о<EFBFBD><D0BE>´<EFBFBD>.
// ij<><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> affect, quest<73><74> load <20>DZ<EFBFBD> <20><><EFBFBD><EFBFBD> DragonSoul_Initialize<7A><65> ȣ<><C8A3><EFBFBD>ϸ<EFBFBD> <20>ȵȴ<C8B5>.
// affect<63><74> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>Ǿ<EFBFBD> LoadAffect<63><74><EFBFBD><EFBFBD> ȣ<><C8A3><EFBFBD><EFBFBD>.
void CHARACTER::DragonSoul_Initialize()
{
for (int i = INVENTORY_MAX_NUM + WEAR_MAX_NUM; i < DRAGON_SOUL_EQUIP_SLOT_END; i++)
{
LPITEM pItem = GetItem(TItemPos(INVENTORY, i));
if (NULL != pItem)
pItem->SetSocket(ITEM_SOCKET_DRAGON_SOUL_ACTIVE_IDX, 0);
}
if (FindAffect(AFFECT_DRAGON_SOUL_DECK_0))
{
DragonSoul_ActivateDeck(DRAGON_SOUL_DECK_0);
}
else if (FindAffect(AFFECT_DRAGON_SOUL_DECK_1))
{
DragonSoul_ActivateDeck(DRAGON_SOUL_DECK_1);
}
}
int CHARACTER::DragonSoul_GetActiveDeck() const
{
return m_pointsInstant.iDragonSoulActiveDeck;
}
bool CHARACTER::DragonSoul_IsDeckActivated() const
{
return m_pointsInstant.iDragonSoulActiveDeck >= 0;
}
bool CHARACTER::DragonSoul_IsQualified() const
{
return FindAffect(AFFECT_DRAGON_SOUL_QUALIFIED) != NULL;
}
void CHARACTER::DragonSoul_GiveQualification()
{
if(NULL == FindAffect(AFFECT_DRAGON_SOUL_QUALIFIED))
{
LogManager::instance().CharLog(this, 0, "DS_QUALIFIED", "");
}
AddAffect(AFFECT_DRAGON_SOUL_QUALIFIED, APPLY_NONE, 0, AFF_NONE, INFINITE_AFFECT_DURATION, 0, false, false);
//SetQuestFlag("dragon_soul.is_qualified", 1);
//// <20>ڰ<EFBFBD><DAB0>ִٸ<D6B4> POINT_DRAGON_SOUL_IS_QUALIFIED<45><44> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1
//PointChange(POINT_DRAGON_SOUL_IS_QUALIFIED, 1 - GetPoint(POINT_DRAGON_SOUL_IS_QUALIFIED));
}
bool CHARACTER::DragonSoul_ActivateDeck(int deck_idx)
{
if (deck_idx < DRAGON_SOUL_DECK_0 || deck_idx >= DRAGON_SOUL_DECK_MAX_NUM)
{
return false;
}
if (DragonSoul_GetActiveDeck() == deck_idx)
return true;
DragonSoul_DeactivateAll();
if (!DragonSoul_IsQualified())
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD> <20><><EFBFBD>ڰ<EFBFBD> Ȱ<><C8B0>ȭ<EFBFBD><C8AD><EFBFBD><EFBFBD> <20>ʾҽ<CABE><D2BD>ϴ<EFBFBD>."));
return false;
}
AddAffect(AFFECT_DRAGON_SOUL_DECK_0 + deck_idx, APPLY_NONE, 0, 0, INFINITE_AFFECT_DURATION, 0, false);
m_pointsInstant.iDragonSoulActiveDeck = deck_idx;
for (int i = DRAGON_SOUL_EQUIP_SLOT_START + DS_SLOT_MAX * deck_idx;
i < DRAGON_SOUL_EQUIP_SLOT_START + DS_SLOT_MAX * (deck_idx + 1); i++)
{
LPITEM pItem = GetInventoryItem(i);
if (NULL != pItem)
DSManager::instance().ActivateDragonSoul(pItem);
}
}
void CHARACTER::DragonSoul_DeactivateAll()
{
for (int i = DRAGON_SOUL_EQUIP_SLOT_START; i < DRAGON_SOUL_EQUIP_SLOT_END; i++)
{
DSManager::instance().DeactivateDragonSoul(GetInventoryItem(i), true);
}
m_pointsInstant.iDragonSoulActiveDeck = -1;
RemoveAffect(AFFECT_DRAGON_SOUL_DECK_0);
RemoveAffect(AFFECT_DRAGON_SOUL_DECK_1);
}
void CHARACTER::DragonSoul_CleanUp()
{
for (int i = DRAGON_SOUL_EQUIP_SLOT_START; i < DRAGON_SOUL_EQUIP_SLOT_END; i++)
{
DSManager::instance().DeactivateDragonSoul(GetInventoryItem(i), true);
}
}
bool CHARACTER::DragonSoul_RefineWindow_Open(LPENTITY pEntity)
{
if (NULL == m_pointsInstant.m_pDragonSoulRefineWindowOpener)
{
m_pointsInstant.m_pDragonSoulRefineWindowOpener = pEntity;
}
TPacketGCDragonSoulRefine PDS;
PDS.header = HEADER_GC_DRAGON_SOUL_REFINE;
PDS.bSubType = DS_SUB_HEADER_OPEN;
LPDESC d = GetDesc();
if (NULL == d)
{
sys_err ("User(%s)'s DESC is NULL POINT.", GetName());
return false;
}
d->Packet(&PDS, sizeof(PDS));
return true;
}
bool CHARACTER::DragonSoul_RefineWindow_Close()
{
m_pointsInstant.m_pDragonSoulRefineWindowOpener = NULL;
return true;
}
bool CHARACTER::DragonSoul_RefineWindow_CanRefine()
{
return NULL != m_pointsInstant.m_pDragonSoulRefineWindowOpener;
}

View File

@ -0,0 +1,93 @@
#include "stdafx.h"
#include "char.h"
#include "config.h"
#include "event.h"
#include "HackShield.h"
#include "log.h"
#include "desc.h"
#include "packet.h"
EVENTINFO(hackshield_event_info)
{
DynamicCharacterPtr CharPtr;
};
EVENTFUNC(hackshield_event)
{
hackshield_event_info* info = dynamic_cast<hackshield_event_info*>( event->info );
if ( info == NULL )
{
sys_err( "hackshield_event> <Factor> Null pointer" );
return 0;
}
LPCHARACTER ch = info->CharPtr;
if (NULL == ch)
{
sys_err("HShield: character pointer is null");
return 0;
}
if (NULL == ch->GetDesc())
{
sys_err("HShield: character has no descriptor");
return 0;
}
if (false == ch->GetHackShieldCheckMode())
{
if (false == CHackShieldManager::instance().SendCheckPacket(ch))
{
return 0;
}
else
{
ch->SetHackShieldCheckMode(true);
return HackShield_CheckCycleTime;
}
}
sys_log(0, "HShield: no response from Player(%u)", ch->GetPlayerID());
LogManager::instance().HackShieldLog(0, ch);
ch->m_HackShieldCheckEvent = NULL;
ch->GetDesc()->SetPhase(PHASE_CLOSE);
return 0;
}
void CHARACTER::StartHackShieldCheckCycle(int seconds)
{
StopHackShieldCheckCycle();
if (false == isHackShieldEnable)
return;
hackshield_event_info* info = AllocEventInfo<hackshield_event_info>();
info->CharPtr = this;
m_HackShieldCheckEvent = event_create(hackshield_event, info, seconds);
sys_log(0, "HShield: StartHackShieldCheckCycle %d", seconds);
}
void CHARACTER::StopHackShieldCheckCycle()
{
if (NULL != m_HackShieldCheckEvent)
{
event_cancel(&m_HackShieldCheckEvent);
m_HackShieldCheckEvent = NULL;
sys_log(0, "HShield: StopHackShieldCheckCycle");
}
}

387
game/src/char_horse.cpp Normal file
View File

@ -0,0 +1,387 @@
#include "stdafx.h"
#include "config.h"
#include "char.h"
#include "char_manager.h"
#include "packet.h"
#include "guild.h"
#include "vector.h"
#include "questmanager.h"
#include "item.h"
#include "horsename_manager.h"
#include "locale_service.h"
#include "arena.h"
#include "../../common/VnumHelper.h"
bool CHARACTER::StartRiding()
{
if (IsDead() == true)
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>¿<EFBFBD><C2BF><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Ż <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
return false;
}
if (IsPolymorphed())
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>¿<EFBFBD><C2BF><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Ż <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
return false;
}
// <20>νõ<CEBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> Ÿ<><C5B8> <20><><EFBFBD><EFBFBD>
LPITEM armor = GetWear(WEAR_BODY);
if (armor && (armor->GetVnum() >= 11901 && armor->GetVnum() <= 11904))
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>¿<EFBFBD><C2BF><EFBFBD> <20><><EFBFBD><EFBFBD> Ż <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
return false;
}
if (LC_IsCanada() == true)
{
if (CArenaManager::instance().IsArenaMap(GetMapIndex()) == true)
return false;
}
DWORD dwMountVnum = m_chHorse ? m_chHorse->GetRaceNum() : GetMyHorseVnum();
if (false == CHorseRider::StartRiding())
{
if (GetHorseLevel() <= 0)
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʽ<EFBFBD><CABD>ϴ<EFBFBD>."));
else if (GetHorseHealth() <= 0)
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>׾<EFBFBD><D7BE>ִ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>Դϴ<D4B4>."));
else if (GetHorseStamina() <= 0)
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>׹̳ʰ<CCB3> <20><><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD> Ż <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
return false;
}
// <20><>ȯ<EFBFBD><C8AF> <20><> <20><><EFBFBD>ְ<EFBFBD>
HorseSummon(false);
MountVnum(dwMountVnum);
if(test_server)
sys_log(0, "Ride Horse : %s ", GetName());
return true;
}
bool CHARACTER::StopRiding()
{
if (CHorseRider::StopRiding())
{
quest::CQuestManager::instance().Unmount(GetPlayerID());
if (!IsDead() && !IsStun())
{
DWORD dwOldVnum = GetMountVnum();
MountVnum(0);
// [NOTE] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20>ڱⰡ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD> <20><><EFBFBD><EFBFBD>
HorseSummon(true, false, dwOldVnum);
}
else
{
m_dwMountVnum = 0;
ComputePoints();
UpdatePacket();
}
PointChange(POINT_ST, 0);
PointChange(POINT_DX, 0);
PointChange(POINT_HT, 0);
PointChange(POINT_IQ, 0);
return true;
}
return false;
}
EVENTFUNC(horse_dead_event)
{
char_event_info* info = dynamic_cast<char_event_info*>( event->info );
if ( info == NULL )
{
sys_err( "horse_dead_event> <Factor> Null pointer" );
return 0;
}
// <Factor>
LPCHARACTER ch = info->ch;
if (ch == NULL) {
return 0;
}
ch->HorseSummon(false);
return 0;
}
void CHARACTER::SetRider(LPCHARACTER ch)
{
if (m_chRider)
m_chRider->ClearHorseInfo();
m_chRider = ch;
if (m_chRider)
m_chRider->SendHorseInfo();
}
LPCHARACTER CHARACTER::GetRider() const
{
return m_chRider;
}
void CHARACTER::HorseSummon(bool bSummon, bool bFromFar, DWORD dwVnum, const char* pPetName)
{
if ( bSummon )
{
//NOTE : summon<6F>ߴµ<DFB4> <20>̹<EFBFBD> horse<73><65> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ƹ<EFBFBD><C6B9>͵<EFBFBD> <20><><EFBFBD>Ѵ<EFBFBD>.
if( m_chHorse != NULL )
return;
if (GetHorseLevel() <= 0)
return;
// <20><><EFBFBD>𰡸<EFBFBD> Ÿ<><C5B8> <20>ִٸ<D6B4> <20><><EFBFBD><EFBFBD>
if (IsRiding())
return;
sys_log(0, "HorseSummon : %s lv:%d bSummon:%d fromFar:%d", GetName(), GetLevel(), bSummon, bFromFar);
long x = GetX();
long y = GetY();
if (GetHorseHealth() <= 0)
bFromFar = false;
if (bFromFar)
{
x += (number(0, 1) * 2 - 1) * number(2000, 2500);
y += (number(0, 1) * 2 - 1) * number(2000, 2500);
}
else
{
x += number(-100, 100);
y += number(-100, 100);
}
m_chHorse = CHARACTER_MANAGER::instance().SpawnMob(
(0 == dwVnum) ? GetMyHorseVnum() : dwVnum,
GetMapIndex(),
x, y,
GetZ(), false, (int)(GetRotation()+180), false);
if (!m_chHorse)
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD> <20><>ȯ<EFBFBD><C8AF> <20><><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
return;
}
if (GetHorseHealth() <= 0)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3> <20>ְ<EFBFBD> <20>ϴ<EFBFBD> ó<><C3B3>
m_chHorse->SetPosition(POS_DEAD);
// <20><><EFBFBD><EFBFBD><EFBFBD>ð<EFBFBD><C3B0>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
char_event_info* info = AllocEventInfo<char_event_info>();
info->ch = this;
m_chHorse->m_pkDeadEvent = event_create(horse_dead_event, info, PASSES_PER_SEC(60));
}
m_chHorse->SetLevel(GetHorseLevel());
const char* pHorseName = CHorseNameManager::instance().GetHorseName(GetPlayerID());
if ( pHorseName != NULL && strlen(pHorseName) != 0 )
{
m_chHorse->m_stName = pHorseName;
}
else
{
m_chHorse->m_stName = GetName();
m_chHorse->m_stName += LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>");
}
if (!m_chHorse->Show(GetMapIndex(), x, y, GetZ()))
{
M2_DESTROY_CHARACTER(m_chHorse);
sys_err("cannot show monster");
m_chHorse = NULL;
return;
}
if ((GetHorseHealth() <= 0))
{
TPacketGCDead pack;
pack.header = HEADER_GC_DEAD;
pack.vid = m_chHorse->GetVID();
PacketAround(&pack, sizeof(pack));
}
m_chHorse->SetRider(this);
}
else
{
if (!m_chHorse)
return;
LPCHARACTER chHorse = m_chHorse;
chHorse->SetRider(NULL); // m_chHorse assign to NULL
if (!bFromFar)
{
M2_DESTROY_CHARACTER(chHorse);
}
else
{
// <20>־<EFBFBD><D6BE><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ó<><C3B3> <20>ϱ<EFBFBD>
chHorse->SetNowWalking(false);
float fx, fy;
chHorse->SetRotation(GetDegreeFromPositionXY(chHorse->GetX(), chHorse->GetY(), GetX(), GetY())+180);
GetDeltaByDegree(chHorse->GetRotation(), 3500, &fx, &fy);
chHorse->Goto((long)(chHorse->GetX()+fx), (long) (chHorse->GetY()+fy));
chHorse->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
}
m_chHorse = NULL;
}
}
DWORD CHARACTER::GetMyHorseVnum() const
{
int delta = 0;
if (GetGuild())
{
++delta;
if (GetGuild()->GetMasterPID() == GetPlayerID())
++delta;
}
return c_aHorseStat[GetHorseLevel()].iNPCRace + delta;
}
void CHARACTER::HorseDie()
{
CHorseRider::HorseDie();
HorseSummon(false);
}
bool CHARACTER::ReviveHorse()
{
if (CHorseRider::ReviveHorse())
{
HorseSummon(false);
HorseSummon(true);
return true;
}
return false;
}
void CHARACTER::ClearHorseInfo()
{
if (!IsHorseRiding())
{
ChatPacket(CHAT_TYPE_COMMAND, "hide_horse_state");
m_bSendHorseLevel = 0;
m_bSendHorseHealthGrade = 0;
m_bSendHorseStaminaGrade = 0;
}
m_chHorse = NULL;
}
void CHARACTER::SendHorseInfo()
{
if (m_chHorse || IsHorseRiding())
{
int iHealthGrade;
int iStaminaGrade;
/*
HP
3: 70% < ~ <= 100%
2: 30% < ~ <= 70%
1: 0% < ~ <= 30%
0: <20><><EFBFBD><EFBFBD>
STM
3: 71% < ~ <= 100%
2: 31% < ~ <= 70%
1: 10% < ~ <= 30%
0: ~ <= 10%
*/
if (GetHorseHealth() == 0)
iHealthGrade = 0;
else if (GetHorseHealth() * 10 <= GetHorseMaxHealth() * 3)
iHealthGrade = 1;
else if (GetHorseHealth() * 10 <= GetHorseMaxHealth() * 7)
iHealthGrade = 2;
else
iHealthGrade = 3;
if (GetHorseStamina() * 10 <= GetHorseMaxStamina())
iStaminaGrade = 0;
else if (GetHorseStamina() * 10 <= GetHorseMaxStamina() * 3)
iStaminaGrade = 1;
else if (GetHorseStamina() * 10 <= GetHorseMaxStamina() * 7)
iStaminaGrade = 2;
else
iStaminaGrade = 3;
if (m_bSendHorseLevel != GetHorseLevel() ||
m_bSendHorseHealthGrade != iHealthGrade ||
m_bSendHorseStaminaGrade != iStaminaGrade)
{
ChatPacket(CHAT_TYPE_COMMAND, "horse_state %d %d %d", GetHorseLevel(), iHealthGrade, iStaminaGrade);
// FIX : Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE> "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>" <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ǥ<><C7A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Լ<EFBFBD> <20><><EFBFBD>Կ<EFBFBD> return<72><6E><EFBFBD><EFBFBD><EFBFBD>ν<EFBFBD> <20>Ʒ<EFBFBD> <20>ڵ带 <20><><EFBFBD><EFBFBD><EFBFBD>Ѵٸ<D1B4>
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ѵ<EFBFBD><D1B4><EFBFBD> <20><>ȯ<EFBFBD>ϴ<EFBFBD> <20><><EFBFBD>ù<EFBFBD><C3B9><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>װ<EFBFBD> <20><><EFBFBD><EFBFBD>.. <20><>Ȯ<EFBFBD><C8AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ľ<EFBFBD> <20><><EFBFBD>غ<EFBFBD><D8BA><EFBFBD> <20><><EFBFBD><EFBFBD>.
m_bSendHorseLevel = GetHorseLevel();
m_bSendHorseHealthGrade = iHealthGrade;
m_bSendHorseStaminaGrade = iStaminaGrade;
}
}
}
bool CHARACTER::CanUseHorseSkill()
{
if(IsRiding())
{
if (GetHorseGrade() == 3)
return true;
else
return false;
if(GetMountVnum())
{
if (GetMountVnum() >= 20209 && GetMountVnum() <= 20212)
return true;
//<2F>󸶴<EFBFBD> <20>
if (CMobVnumHelper::IsRamadanBlackHorse(GetMountVnum()))
return true;
}
else
return false;
}
return false;
}
void CHARACTER::SetHorseLevel(int iLevel)
{
CHorseRider::SetHorseLevel(iLevel);
SetSkillLevel(SKILL_HORSE, GetHorseLevel());
}

7541
game/src/char_item.cpp Normal file

File diff suppressed because it is too large Load Diff

1122
game/src/char_manager.cpp Normal file

File diff suppressed because it is too large Load Diff

175
game/src/char_manager.h Normal file
View File

@ -0,0 +1,175 @@
#ifndef __INC_METIN_II_GAME_CHARACTER_MANAGER_H__
#define __INC_METIN_II_GAME_CHARACTER_MANAGER_H__
#ifdef M2_USE_POOL
#include "pool.h"
#endif
#include "../../common/stl.h"
#include "../../common/length.h"
#include "vid.h"
class CDungeon;
class CHARACTER;
class CharacterVectorInteractor;
class CHARACTER_MANAGER : public singleton<CHARACTER_MANAGER>
{
public:
typedef TR1_NS::unordered_map<std::string, LPCHARACTER> NAME_MAP;
CHARACTER_MANAGER();
virtual ~CHARACTER_MANAGER();
void Destroy();
void GracefulShutdown(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>˴ٿ<CBB4><D9BF><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>. PC<50><43> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ű<EFBFBD><C5B0> Destroy <20>Ѵ<EFBFBD>.
DWORD AllocVID();
LPCHARACTER CreateCharacter(const char * name, DWORD dwPID = 0);
#ifndef DEBUG_ALLOC
void DestroyCharacter(LPCHARACTER ch);
#else
void DestroyCharacter(LPCHARACTER ch, const char* file, size_t line);
#endif
void Update(int iPulse);
LPCHARACTER SpawnMob(DWORD dwVnum, long lMapIndex, long x, long y, long z, bool bSpawnMotion = false, int iRot = -1, bool bShow = true);
LPCHARACTER SpawnMobRange(DWORD dwVnum, long lMapIndex, int sx, int sy, int ex, int ey, bool bIsException=false, bool bSpawnMotion = false , bool bAggressive = false);
LPCHARACTER SpawnGroup(DWORD dwVnum, long lMapIndex, int sx, int sy, int ex, int ey, LPREGEN pkRegen = NULL, bool bAggressive_ = false, LPDUNGEON pDungeon = NULL);
bool SpawnGroupGroup(DWORD dwVnum, long lMapIndex, int sx, int sy, int ex, int ey, LPREGEN pkRegen = NULL, bool bAggressive_ = false, LPDUNGEON pDungeon = NULL);
bool SpawnMoveGroup(DWORD dwVnum, long lMapIndex, int sx, int sy, int ex, int ey, int tx, int ty, LPREGEN pkRegen = NULL, bool bAggressive_ = false);
LPCHARACTER SpawnMobRandomPosition(DWORD dwVnum, long lMapIndex);
void SelectStone(LPCHARACTER pkChrStone);
NAME_MAP & GetPCMap() { return m_map_pkPCChr; }
LPCHARACTER Find(DWORD dwVID);
LPCHARACTER Find(const VID & vid);
LPCHARACTER FindPC(const char * name);
LPCHARACTER FindByPID(DWORD dwPID);
bool AddToStateList(LPCHARACTER ch);
void RemoveFromStateList(LPCHARACTER ch);
// DelayedSave: <20><EFBFBD><EEB6B0> <20><>ƾ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ؾ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ϸ<EFBFBD> <20><><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʹ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD> "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>" <20><><EFBFBD><EFBFBD> ǥ<>ø<EFBFBD> <20>صΰ<D8B5> <20><><EFBFBD><EFBFBD>
// (<28><>: 1 frame) <20>Ŀ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ų<EFBFBD><C5B2>.
void DelayedSave(LPCHARACTER ch);
bool FlushDelayedSave(LPCHARACTER ch); // Delayed <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20>ִٸ<D6B4> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>. <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>.
void ProcessDelayedSave();
template<class Func> Func for_each_pc(Func f);
void RegisterForMonsterLog(LPCHARACTER ch);
void UnregisterForMonsterLog(LPCHARACTER ch);
void PacketMonsterLog(LPCHARACTER ch, const void* buf, int size);
void KillLog(DWORD dwVnum);
void RegisterRaceNum(DWORD dwVnum);
void RegisterRaceNumMap(LPCHARACTER ch);
void UnregisterRaceNumMap(LPCHARACTER ch);
bool GetCharactersByRaceNum(DWORD dwRaceNum, CharacterVectorInteractor & i);
LPCHARACTER FindSpecifyPC(unsigned int uiJobFlag, long lMapIndex, LPCHARACTER except=NULL, int iMinLevel = 1, int iMaxLevel = PLAYER_MAX_LEVEL_CONST);
void SetMobItemRate(int value) { m_iMobItemRate = value; }
void SetMobDamageRate(int value) { m_iMobDamageRate = value; }
void SetMobGoldAmountRate(int value) { m_iMobGoldAmountRate = value; }
void SetMobGoldDropRate(int value) { m_iMobGoldDropRate = value; }
void SetMobExpRate(int value) { m_iMobExpRate = value; }
void SetMobItemRatePremium(int value) { m_iMobItemRatePremium = value; }
void SetMobGoldAmountRatePremium(int value) { m_iMobGoldAmountRatePremium = value; }
void SetMobGoldDropRatePremium(int value) { m_iMobGoldDropRatePremium = value; }
void SetMobExpRatePremium(int value) { m_iMobExpRatePremium = value; }
void SetUserDamageRatePremium(int value) { m_iUserDamageRatePremium = value; }
void SetUserDamageRate(int value ) { m_iUserDamageRate = value; }
int GetMobItemRate(LPCHARACTER ch);
int GetMobDamageRate(LPCHARACTER ch);
int GetMobGoldAmountRate(LPCHARACTER ch);
int GetMobGoldDropRate(LPCHARACTER ch);
int GetMobExpRate(LPCHARACTER ch);
int GetUserDamageRate(LPCHARACTER ch);
void SendScriptToMap(long lMapIndex, const std::string & s);
bool BeginPendingDestroy();
void FlushPendingDestroy();
private:
int m_iMobItemRate;
int m_iMobDamageRate;
int m_iMobGoldAmountRate;
int m_iMobGoldDropRate;
int m_iMobExpRate;
int m_iMobItemRatePremium;
int m_iMobGoldAmountRatePremium;
int m_iMobGoldDropRatePremium;
int m_iMobExpRatePremium;
int m_iUserDamageRate;
int m_iUserDamageRatePremium;
int m_iVIDCount;
TR1_NS::unordered_map<DWORD, LPCHARACTER> m_map_pkChrByVID;
TR1_NS::unordered_map<DWORD, LPCHARACTER> m_map_pkChrByPID;
NAME_MAP m_map_pkPCChr;
char dummy1[1024]; // memory barrier
CHARACTER_SET m_set_pkChrState; // FSM<53><4D> <20><><EFBFBD>ư<EFBFBD><C6B0><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD>
CHARACTER_SET m_set_pkChrForDelayedSave;
CHARACTER_SET m_set_pkChrMonsterLog;
LPCHARACTER m_pkChrSelectedStone;
std::map<DWORD, DWORD> m_map_dwMobKillCount;
std::set<DWORD> m_set_dwRegisteredRaceNum;
std::map<DWORD, CHARACTER_SET> m_map_pkChrByRaceNum;
bool m_bUsePendingDestroy;
CHARACTER_SET m_set_pkChrPendingDestroy;
#ifdef M2_USE_POOL
ObjectPool<CHARACTER> pool_;
#endif
};
template<class Func>
Func CHARACTER_MANAGER::for_each_pc(Func f)
{
TR1_NS::unordered_map<DWORD, LPCHARACTER>::iterator it;
for (it = m_map_pkChrByPID.begin(); it != m_map_pkChrByPID.end(); ++it)
f(it->second);
return f;
}
class CharacterVectorInteractor : public CHARACTER_VECTOR
{
public:
CharacterVectorInteractor() : m_bMyBegin(false) { }
CharacterVectorInteractor(const CHARACTER_SET & r);
virtual ~CharacterVectorInteractor();
private:
bool m_bMyBegin;
};
#ifndef DEBUG_ALLOC
#define M2_DESTROY_CHARACTER(ptr) CHARACTER_MANAGER::instance().DestroyCharacter(ptr)
#else
#define M2_DESTROY_CHARACTER(ptr) CHARACTER_MANAGER::instance().DestroyCharacter(ptr, __FILE__, __LINE__)
#endif
#endif

156
game/src/char_quickslot.cpp Normal file
View File

@ -0,0 +1,156 @@
#include "stdafx.h"
#include "constants.h"
#include "char.h"
#include "desc.h"
#include "desc_manager.h"
#include "packet.h"
#include "item.h"
/////////////////////////////////////////////////////////////////////////////
// QUICKSLOT HANDLING
/////////////////////////////////////////////////////////////////////////////
void CHARACTER::SyncQuickslot(BYTE bType, BYTE bOldPos, BYTE bNewPos) // bNewPos == 255 <20><> DELETE
{
if (bOldPos == bNewPos)
return;
for (int i = 0; i < QUICKSLOT_MAX_NUM; ++i)
{
if (m_quickslot[i].type == bType && m_quickslot[i].pos == bOldPos)
{
if (bNewPos == 255)
DelQuickslot(i);
else
{
TQuickslot slot;
slot.type = bType;
slot.pos = bNewPos;
SetQuickslot(i, slot);
}
}
}
}
bool CHARACTER::GetQuickslot(BYTE pos, TQuickslot ** ppSlot)
{
if (pos >= QUICKSLOT_MAX_NUM)
return false;
*ppSlot = &m_quickslot[pos];
return true;
}
bool CHARACTER::SetQuickslot(BYTE pos, TQuickslot & rSlot)
{
struct packet_quickslot_add pack_quickslot_add;
if (pos >= QUICKSLOT_MAX_NUM)
return false;
if (rSlot.type >= QUICKSLOT_TYPE_MAX_NUM)
return false;
for (int i = 0; i < QUICKSLOT_MAX_NUM; ++i)
{
if (rSlot.type == 0)
continue;
else if (m_quickslot[i].type == rSlot.type && m_quickslot[i].pos == rSlot.pos)
DelQuickslot(i);
}
TItemPos srcCell(INVENTORY, rSlot.pos);
switch (rSlot.type)
{
case QUICKSLOT_TYPE_ITEM:
if (false == srcCell.IsDefaultInventoryPosition() && false == srcCell.IsBeltInventoryPosition())
return false;
break;
case QUICKSLOT_TYPE_SKILL:
if ((int) rSlot.pos >= SKILL_MAX_NUM)
return false;
break;
case QUICKSLOT_TYPE_COMMAND:
break;
default:
return false;
}
m_quickslot[pos] = rSlot;
if (GetDesc())
{
pack_quickslot_add.header = HEADER_GC_QUICKSLOT_ADD;
pack_quickslot_add.pos = pos;
pack_quickslot_add.slot = m_quickslot[pos];
GetDesc()->Packet(&pack_quickslot_add, sizeof(pack_quickslot_add));
}
return true;
}
bool CHARACTER::DelQuickslot(BYTE pos)
{
struct packet_quickslot_del pack_quickslot_del;
if (pos >= QUICKSLOT_MAX_NUM)
return false;
memset(&m_quickslot[pos], 0, sizeof(TQuickslot));
pack_quickslot_del.header = HEADER_GC_QUICKSLOT_DEL;
pack_quickslot_del.pos = pos;
GetDesc()->Packet(&pack_quickslot_del, sizeof(pack_quickslot_del));
return true;
}
bool CHARACTER::SwapQuickslot(BYTE a, BYTE b)
{
struct packet_quickslot_swap pack_quickslot_swap;
TQuickslot quickslot;
if (a >= QUICKSLOT_MAX_NUM || b >= QUICKSLOT_MAX_NUM)
return false;
// <20><> <20><><EFBFBD><EFBFBD> <20>ڸ<EFBFBD><DAB8><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ٲ۴<D9B2>.
quickslot = m_quickslot[a];
m_quickslot[a] = m_quickslot[b];
m_quickslot[b] = quickslot;
pack_quickslot_swap.header = HEADER_GC_QUICKSLOT_SWAP;
pack_quickslot_swap.pos = a;
pack_quickslot_swap.pos_to = b;
GetDesc()->Packet(&pack_quickslot_swap, sizeof(pack_quickslot_swap));
return true;
}
void CHARACTER::ChainQuickslotItem(LPITEM pItem, BYTE bType, BYTE bOldPos)
{
if (pItem->IsDragonSoul())
return;
for ( int i=0; i < QUICKSLOT_MAX_NUM; ++i )
{
if ( m_quickslot[i].type == bType && m_quickslot[i].pos == bOldPos )
{
TQuickslot slot;
slot.type = bType;
slot.pos = pItem->GetCell();
SetQuickslot(i, slot);
break;
}
}
}

280
game/src/char_resist.cpp Normal file
View File

@ -0,0 +1,280 @@
#include "stdafx.h"
#include "constants.h"
#include "config.h"
#include "char.h"
#include "char_manager.h"
#include "affect.h"
#include "locale_service.h"
// <20><>
const int poison_damage_rate[MOB_RANK_MAX_NUM] =
{
80, 50, 40, 30, 25, 1
};
int GetPoisonDamageRate(LPCHARACTER ch)
{
int iRate;
if (ch->IsPC())
{
if (LC_IsYMIR())
iRate = 40;
else
iRate = 50;
}
else
iRate = poison_damage_rate[ch->GetMobRank()];
iRate = MAX(0, iRate - ch->GetPoint(POINT_POISON_REDUCE));
return iRate;
}
EVENTINFO(TPoisonEventInfo)
{
DynamicCharacterPtr ch;
int count;
DWORD attacker_pid;
TPoisonEventInfo()
: ch()
, count(0)
, attacker_pid(0)
{
}
};
EVENTFUNC(poison_event)
{
TPoisonEventInfo * info = dynamic_cast<TPoisonEventInfo *>( event->info );
if ( info == NULL )
{
sys_err( "poison_event> <Factor> Null pointer" );
return 0;
}
LPCHARACTER ch = info->ch;
if (ch == NULL) { // <Factor>
return 0;
}
LPCHARACTER pkAttacker = CHARACTER_MANAGER::instance().FindByPID(info->attacker_pid);
int dam = ch->GetMaxHP() * GetPoisonDamageRate(ch) / 1000;
if (test_server) ch->ChatPacket(CHAT_TYPE_NOTICE, "Poison Damage %d", dam);
if (ch->Damage(pkAttacker, dam, DAMAGE_TYPE_POISON))
{
ch->m_pkPoisonEvent = NULL;
return 0;
}
--info->count;
if (info->count)
return PASSES_PER_SEC(3);
else
{
ch->m_pkPoisonEvent = NULL;
return 0;
}
}
EVENTINFO(TFireEventInfo)
{
DynamicCharacterPtr ch;
int count;
int amount;
DWORD attacker_pid;
TFireEventInfo()
: ch()
, count(0)
, amount(0)
, attacker_pid(0)
{
}
};
EVENTFUNC(fire_event)
{
TFireEventInfo * info = dynamic_cast<TFireEventInfo *>( event->info );
if ( info == NULL )
{
sys_err( "fire_event> <Factor> Null pointer" );
return 0;
}
LPCHARACTER ch = info->ch;
if (ch == NULL) { // <Factor>
return 0;
}
LPCHARACTER pkAttacker = CHARACTER_MANAGER::instance().FindByPID(info->attacker_pid);
int dam = info->amount;
if (test_server) ch->ChatPacket(CHAT_TYPE_NOTICE, "Fire Damage %d", dam);
if (ch->Damage(pkAttacker, dam, DAMAGE_TYPE_FIRE))
{
ch->m_pkFireEvent = NULL;
return 0;
}
--info->count;
if (info->count)
return PASSES_PER_SEC(3);
else
{
ch->m_pkFireEvent = NULL;
return 0;
}
}
/*
LEVEL<45><4C> <20><><EFBFBD><EFBFBD>..
+8 0%
+7 5%
+6 10%
+5 30%
+4 50%
+3 70%
+2 80%
+1 90%
+0 100%
-1 100%
-2 100%
-3 100%
-4 100%
-5 100%
-6 100%
-7 100%
-8 100%
*/
static int poison_level_adjust[9] =
{
100, 90, 80, 70, 50, 30, 10, 5, 0
};
void CHARACTER::AttackedByFire(LPCHARACTER pkAttacker, int amount, int count)
{
if (m_pkFireEvent)
return;
AddAffect(AFFECT_FIRE, POINT_NONE, 0, AFF_FIRE, count*3+1, 0, true);
TFireEventInfo* info = AllocEventInfo<TFireEventInfo>();
info->ch = this;
info->count = count;
info->amount = amount;
info->attacker_pid = pkAttacker->GetPlayerID();
m_pkFireEvent = event_create(fire_event, info, 1);
}
void CHARACTER::AttackedByPoison(LPCHARACTER pkAttacker)
{
if (m_pkPoisonEvent)
return;
if (m_bHasPoisoned && !IsPC()) // <20><><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ѹ<EFBFBD><D1B9><EFBFBD> <20>ɸ<EFBFBD><C9B8><EFBFBD>.
return;
if (pkAttacker && pkAttacker->GetLevel() < GetLevel())
{
int delta = GetLevel() - pkAttacker->GetLevel();
if (delta > 8)
delta = 8;
if (number(1, 100) > poison_level_adjust[delta])
return;
}
/*if (IsImmune(IMMUNE_POISON))
return;*/
// <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20>ɷȴ<C9B7>!
m_bHasPoisoned = true;
AddAffect(AFFECT_POISON, POINT_NONE, 0, AFF_POISON, POISON_LENGTH + 1, 0, true);
TPoisonEventInfo* info = AllocEventInfo<TPoisonEventInfo>();
info->ch = this;
info->count = 10;
info->attacker_pid = pkAttacker?pkAttacker->GetPlayerID():0;
m_pkPoisonEvent = event_create(poison_event, info, 1);
if (test_server && pkAttacker)
{
char buf[256];
snprintf(buf, sizeof(buf), "POISON %s -> %s", pkAttacker->GetName(), GetName());
pkAttacker->ChatPacket(CHAT_TYPE_INFO, "%s", buf);
}
}
void CHARACTER::RemoveFire()
{
RemoveAffect(AFFECT_FIRE);
event_cancel(&m_pkFireEvent);
}
void CHARACTER::RemovePoison()
{
RemoveAffect(AFFECT_POISON);
event_cancel(&m_pkPoisonEvent);
}
void CHARACTER::ApplyMobAttribute(const TMobTable* table)
{
for (int i = 0; i < MOB_ENCHANTS_MAX_NUM; ++i)
{
if (table->cEnchants[i] != 0)
ApplyPoint(aiMobEnchantApplyIdx[i], table->cEnchants[i]);
}
for (int i = 0; i < MOB_RESISTS_MAX_NUM; ++i)
{
if (table->cResists[i] != 0)
ApplyPoint(aiMobResistsApplyIdx[i], table->cResists[i]);
}
}
bool CHARACTER::IsImmune(DWORD dwImmuneFlag)
{
if (IS_SET(m_pointsInstant.dwImmuneFlag, dwImmuneFlag))
{
int immune_pct = 90;
int percent = number(1, 100);
if (percent <= immune_pct) // 90% Immune
{
if (test_server && IsPC())
ChatPacket(CHAT_TYPE_PARTY, "<IMMUNE_SUCCESS> (%s)", GetName());
return true;
}
else
{
if (test_server && IsPC())
ChatPacket(CHAT_TYPE_PARTY, "<IMMUNE_FAIL> (%s)", GetName());
return false;
}
}
if (test_server && IsPC())
ChatPacket(CHAT_TYPE_PARTY, "<IMMUNE_FAIL> (%s) NO_IMMUNE_FLAG", GetName());
return false;
}

3600
game/src/char_skill.cpp Normal file

File diff suppressed because it is too large Load Diff

1230
game/src/char_state.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
#include "check_server.h"
std::vector<std::string> CheckServer::keys_;
bool CheckServer::fail_ = true;

48
game/src/check_server.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef _M2_CHECK_SERVER_KEY_H_
#define _M2_CHECK_SERVER_KEY_H_
#include <string>
#include <vector>
#include "CheckServerKey.h"
class CheckServer
{
public:
static FORCEINLINE void AddServerKey(const char* serverKey)
{
keys_.push_back(serverKey);
}
static FORCEINLINE bool CheckIp(const char* ip)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ȱɸ<C8B0><C9B8><EFBFBD> üũ <20><><EFBFBD><EFBFBD>
#ifndef _USE_SERVER_KEY_
fail_ = false;
return true;
#endif
for (int i = 0; i < keys_.size(); i++)
{
// <20>ϳ<EFBFBD><CFB3><EFBFBD><EFBFBD><EFBFBD> <20>´<EFBFBD> <20><><EFBFBD><EFBFBD>Ű<EFBFBD><C5B0> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ok
std::string errorString;
if (CheckServerKey(keys_[i].c_str(), ip, "", errorString))
{
fail_ = false;
break;
}
}
return !IsFail();
}
static FORCEINLINE bool IsFail()
{
return fail_;
}
private:
static std::vector<std::string> keys_;
static bool fail_;
};
#endif // #ifndef _M2_CHECK_SERVER_KEY_H_

402
game/src/cipher.cpp Normal file
View File

@ -0,0 +1,402 @@
#include "stdafx.h"
#include "cipher.h"
#ifdef _IMPROVED_PACKET_ENCRYPTION_
#include <cryptopp/modes.h>
#include <cryptopp/nbtheory.h>
#include <cryptopp/osrng.h>
// Diffie-Hellman key agreement
#include <cryptopp/dh.h>
#include <cryptopp/dh2.h>
// AES winner and candidates
//#include <cryptopp/aes.h>
#include <cryptopp/cast.h>
#include <cryptopp/rc6.h>
#include <cryptopp/mars.h>
#include <cryptopp/serpent.h>
#include <cryptopp/twofish.h>
// Other block ciphers
#include <cryptopp/blowfish.h>
#include <cryptopp/camellia.h>
#include <cryptopp/des.h>
#include <cryptopp/idea.h>
#include <cryptopp/rc5.h>
#include <cryptopp/seed.h>
#include <cryptopp/shacal2.h>
#include <cryptopp/skipjack.h>
#include <cryptopp/tea.h>
#include <cryptopp/cryptoppLibLink.h>
using namespace CryptoPP;
// Block cipher algorithm selector abstract base class.
struct BlockCipherAlgorithm {
enum {
kDefault, // to give more chances to default algorithm
// AES winner and candidates
// kAES, // Rijndael
kRC6,
kMARS,
kTwofish,
kSerpent,
kCAST256,
// Other block ciphers
kIDEA,
k3DES, // DES-EDE2
kCamellia,
kSEED,
kRC5,
kBlowfish,
kTEA,
// kSKIPJACK,
kSHACAL2,
// End sentinel
kMaxAlgorithms
};
BlockCipherAlgorithm() {}
virtual ~BlockCipherAlgorithm() {}
static BlockCipherAlgorithm* Pick(int hint);
virtual int GetBlockSize() const = 0;
virtual int GetDefaultKeyLength() const = 0;
virtual int GetIVLength() const = 0;
virtual SymmetricCipher* CreateEncoder(const byte* key, size_t keylen,
const byte* iv) const = 0;
virtual SymmetricCipher* CreateDecoder(const byte* key, size_t keylen,
const byte* iv) const = 0;
};
// Block cipher (with CTR mode) algorithm selector template class.
template<class T>
struct BlockCipherDetail : public BlockCipherAlgorithm {
BlockCipherDetail() {}
virtual ~BlockCipherDetail() {}
virtual int GetBlockSize() const { return T::BLOCKSIZE; }
virtual int GetDefaultKeyLength() const { return T::DEFAULT_KEYLENGTH; }
virtual int GetIVLength() const { return T::IV_LENGTH; }
virtual SymmetricCipher* CreateEncoder(const byte* key, size_t keylen,
const byte* iv) const {
return new typename CTR_Mode<T>::Encryption(key, keylen, iv);
}
virtual SymmetricCipher* CreateDecoder(const byte* key, size_t keylen,
const byte* iv) const {
return new typename CTR_Mode<T>::Decryption(key, keylen, iv);
}
};
// Key agreement scheme abstract class.
class KeyAgreement {
public:
KeyAgreement() {}
virtual ~KeyAgreement() {}
virtual size_t Prepare(void* buffer, size_t* length) = 0;
virtual bool Agree(size_t agreed_length, const void* buffer, size_t length) = 0;
const SecByteBlock& shared() const { return shared_; }
protected:
SecByteBlock shared_;
};
// Crypto++ Unified Diffie-Hellman key agreement scheme implementation.
class DH2KeyAgreement : public KeyAgreement {
public:
DH2KeyAgreement();
virtual ~DH2KeyAgreement();
virtual size_t Prepare(void* buffer, size_t* length);
virtual bool Agree(size_t agreed_length, const void* buffer, size_t length);
private:
DH dh_;
DH2 dh2_;
SecByteBlock spriv_key_;
SecByteBlock epriv_key_;
};
Cipher::Cipher()
: activated_(false), encoder_(NULL), decoder_(NULL), key_agreement_(NULL) {
}
Cipher::~Cipher() {
if (activated_) {
CleanUp();
}
}
void Cipher::CleanUp() {
if (encoder_ != NULL) {
delete encoder_;
encoder_ = NULL;
}
if (decoder_ != NULL) {
delete decoder_;
decoder_ = NULL;
}
if (key_agreement_ != NULL) {
delete key_agreement_;
key_agreement_ = NULL;
}
activated_ = false;
}
size_t Cipher::Prepare(void* buffer, size_t* length) {
assert(key_agreement_ == NULL);
key_agreement_ = new DH2KeyAgreement();
assert(key_agreement_ != NULL);
size_t agreed_length = key_agreement_->Prepare(buffer, length);
if (agreed_length == 0) {
delete key_agreement_;
key_agreement_ = NULL;
}
return agreed_length;
}
bool Cipher::Activate(bool polarity, size_t agreed_length,
const void* buffer, size_t length) {
assert(activated_ == false);
assert(key_agreement_ != NULL);
if (activated_ != false)
return false;
if (key_agreement_->Agree(agreed_length, buffer, length)) {
activated_ = SetUp(polarity);
}
delete key_agreement_;
key_agreement_ = NULL;
return activated_;
}
bool Cipher::SetUp(bool polarity) {
assert(key_agreement_ != NULL);
const SecByteBlock& shared = key_agreement_->shared();
// Pick a block cipher algorithm
if (shared.size() < 2) {
return false;
}
int hint_0 = shared.BytePtr()[*(shared.BytePtr()) % shared.size()];
int hint_1 = shared.BytePtr()[*(shared.BytePtr() + 1) % shared.size()];
BlockCipherAlgorithm* detail_0 = BlockCipherAlgorithm::Pick(hint_0);
BlockCipherAlgorithm* detail_1 = BlockCipherAlgorithm::Pick(hint_1);
assert(detail_0 != NULL);
assert(detail_1 != NULL);
std::auto_ptr<BlockCipherAlgorithm> algorithm_0(detail_0);
std::auto_ptr<BlockCipherAlgorithm> algorithm_1(detail_1);
const size_t key_length_0 = algorithm_0->GetDefaultKeyLength();
const size_t iv_length_0 = algorithm_0->GetBlockSize();
if (shared.size() < key_length_0 || shared.size() < iv_length_0) {
return false;
}
const size_t key_length_1 = algorithm_1->GetDefaultKeyLength();
const size_t iv_length_1 = algorithm_1->GetBlockSize();
if (shared.size() < key_length_1 || shared.size() < iv_length_1) {
return false;
}
// Pick encryption keys and initial vectors
SecByteBlock key_0(key_length_0), iv_0(iv_length_0);
SecByteBlock key_1(key_length_1), iv_1(iv_length_1);
size_t offset;
key_0.Assign(shared, key_length_0);
offset = key_length_0;
#ifdef __GNUC__
offset = std::min(key_length_0, shared.size() - key_length_1);
#else
offset = min(key_length_0, shared.size() - key_length_1);
#endif
key_1.Assign(shared.BytePtr() + offset, key_length_1);
offset = shared.size() - iv_length_0;
iv_0.Assign(shared.BytePtr() + offset, iv_length_0);
offset = (offset < iv_length_1 ? 0 : offset - iv_length_1);
iv_1.Assign(shared.BytePtr() + offset, iv_length_1);
// Create encryption/decryption objects
if (polarity) {
encoder_ = algorithm_1->CreateEncoder(key_1, key_1.size(), iv_1);
decoder_ = algorithm_0->CreateDecoder(key_0, key_0.size(), iv_0);
} else {
encoder_ = algorithm_0->CreateEncoder(key_0, key_0.size(), iv_0);
decoder_ = algorithm_1->CreateDecoder(key_1, key_1.size(), iv_1);
}
assert(encoder_ != NULL);
assert(decoder_ != NULL);
return true;
}
BlockCipherAlgorithm* BlockCipherAlgorithm::Pick(int hint) {
BlockCipherAlgorithm* detail;
int selector = hint % kMaxAlgorithms;
switch (selector) {
// case kAES:
// detail = new BlockCipherDetail<AES>();
break;
case kRC6:
detail = new BlockCipherDetail<RC6>();
break;
case kMARS:
detail = new BlockCipherDetail<MARS>();
break;
case kTwofish:
detail = new BlockCipherDetail<Twofish>();
break;
case kSerpent:
detail = new BlockCipherDetail<Serpent>();
break;
case kCAST256:
detail = new BlockCipherDetail<CAST256>();
break;
case kIDEA:
detail = new BlockCipherDetail<IDEA>();
break;
case k3DES:
detail = new BlockCipherDetail<DES_EDE2>();
break;
case kCamellia:
detail = new BlockCipherDetail<Camellia>();
break;
case kSEED:
detail = new BlockCipherDetail<SEED>();
break;
case kRC5:
detail = new BlockCipherDetail<RC5>();
break;
case kBlowfish:
detail = new BlockCipherDetail<Blowfish>();
break;
case kTEA:
detail = new BlockCipherDetail<TEA>();
break;
// case kSKIPJACK:
// detail = new BlockCipherDetail<SKIPJACK>();
// break;
case kSHACAL2:
detail = new BlockCipherDetail<SHACAL2>();
break;
case kDefault:
default:
detail = new BlockCipherDetail<Twofish>(); // default algorithm
break;
}
return detail;
}
DH2KeyAgreement::DH2KeyAgreement() : dh_(), dh2_(dh_) {
}
DH2KeyAgreement::~DH2KeyAgreement() {
}
size_t DH2KeyAgreement::Prepare(void* buffer, size_t* length) {
// RFC 5114, 1024-bit MODP Group with 160-bit Prime Order Subgroup
// http://tools.ietf.org/html/rfc5114#section-2.1
Integer p("0xB10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6"
"9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0"
"13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70"
"98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0"
"A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708"
"DF1FB2BC2E4A4371");
Integer g("0xA4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F"
"D6406CFF14266D31266FEA1E5C41564B777E690F5504F213"
"160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1"
"909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A"
"D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24"
"855E6EEB22B3B2E5");
Integer q("0xF518AA8781A8DF278ABA4E7D64B7CB9D49462353");
// Schnorr Group primes are of the form p = rq + 1, p and q prime. They
// provide a subgroup order. In the case of 1024-bit MODP Group, the
// security level is 80 bits (based on the 160-bit prime order subgroup).
// For a compare/contrast of using the maximum security level, see
// dh-unified.zip. Also see http://www.cryptopp.com/wiki/Diffie-Hellman
// and http://www.cryptopp.com/wiki/Security_level .
AutoSeededRandomPool rnd;
dh_.AccessGroupParameters().Initialize(p, q, g);
if(!dh_.GetGroupParameters().ValidateGroup(rnd, 3)) {
// Failed to validate prime and generator
return 0;
}
p = dh_.GetGroupParameters().GetModulus();
q = dh_.GetGroupParameters().GetSubgroupOrder();
g = dh_.GetGroupParameters().GetGenerator();
// http://groups.google.com/group/sci.crypt/browse_thread/thread/7dc7eeb04a09f0ce
Integer v = ModularExponentiation(g, q, p);
if(v != Integer::One()) {
// Failed to verify order of the subgroup
return 0;
}
//////////////////////////////////////////////////////////////
spriv_key_.New(dh2_.StaticPrivateKeyLength());
epriv_key_.New(dh2_.EphemeralPrivateKeyLength());
SecByteBlock spub_key(dh2_.StaticPublicKeyLength());
SecByteBlock epub_key(dh2_.EphemeralPublicKeyLength());
dh2_.GenerateStaticKeyPair(rnd, spriv_key_, spub_key);
dh2_.GenerateEphemeralKeyPair(rnd, epriv_key_, epub_key);
// Prepare key agreement data
const size_t spub_key_length = spub_key.size();
const size_t epub_key_length = epub_key.size();
const size_t data_length = spub_key_length + epub_key_length;
if (*length < data_length) {
// Not enough data buffer length
return 0;
}
*length = data_length;
byte* buf = (byte*)buffer;
memcpy(buf, spub_key.BytePtr(), spub_key_length);
memcpy(buf + spub_key_length, epub_key.BytePtr(), epub_key_length);
return dh2_.AgreedValueLength();
}
bool DH2KeyAgreement::Agree(size_t agreed_length, const void* buffer, size_t length) {
if (agreed_length != dh2_.AgreedValueLength()) {
// Shared secret size mismatch
return false;
}
const size_t spub_key_length = dh2_.StaticPublicKeyLength();
const size_t epub_key_length = dh2_.EphemeralPublicKeyLength();
if (length != (spub_key_length + epub_key_length)) {
// Wrong data length
return false;
}
shared_.New(dh2_.AgreedValueLength());
const byte* buf = (const byte*)buffer;
if (!dh2_.Agree(shared_, spriv_key_, epriv_key_, buf, buf + spub_key_length)) {
// Failed to reach shared secret
return false;
}
return true;
}
#endif // _IMPROVED_PACKET_ENCRYPTION_
// EOF cipher.cpp

60
game/src/cipher.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef __CIPHER_H__
#define __CIPHER_H__
#ifdef _IMPROVED_PACKET_ENCRYPTION_
#include <cryptopp/cryptlib.h>
// Forward declaration
class KeyAgreement;
// Communication channel encryption handler.
class Cipher {
public:
Cipher();
~Cipher();
void CleanUp();
// Returns agreed value length in bytes, or zero on failure.
size_t Prepare(void* buffer, size_t* length);
// Try to activate cipher algorithm with agreement data received from peer.
bool Activate(bool polarity, size_t agreed_length,
const void* buffer, size_t length);
// Encrypts the given block of data. (no padding required)
void Encrypt(void* buffer, size_t length) {
assert(activated_);
if (!activated_) {
return;
}
encoder_->ProcessData((byte*)buffer, (const byte*)buffer, length);
}
// Decrypts the given block of data. (no padding required)
void Decrypt(void* buffer, size_t length) {
assert(activated_);
if (!activated_) {
return;
}
decoder_->ProcessData((byte*)buffer, (const byte*)buffer, length);
}
bool activated() const { return activated_; }
void set_activated(bool value) { activated_ = value; }
bool IsKeyPrepared() { return key_agreement_ != NULL; }
private:
bool SetUp(bool polarity);
bool activated_;
CryptoPP::SymmetricCipher* encoder_;
CryptoPP::SymmetricCipher* decoder_;
KeyAgreement* key_agreement_;
};
#endif // _IMPROVED_PACKET_ENCRYPTION_
#endif // __CIPHER_H__

737
game/src/cmd.cpp Normal file
View File

@ -0,0 +1,737 @@
#include "stdafx.h"
#include "utils.h"
#include "config.h"
#include "char.h"
#include "locale_service.h"
#include "log.h"
#include "desc.h"
ACMD(do_user_horse_ride);
ACMD(do_user_horse_back);
ACMD(do_user_horse_feed);
ACMD(do_pcbang_update);
ACMD(do_pcbang_check);
// ADD_COMMAND_SLOW_STUN
ACMD(do_slow);
ACMD(do_stun);
// END_OF_ADD_COMMAND_SLOW_STUN
ACMD(do_warp);
ACMD(do_goto);
ACMD(do_item);
ACMD(do_mob);
ACMD(do_mob_ld);
ACMD(do_mob_aggresive);
ACMD(do_mob_coward);
ACMD(do_mob_map);
ACMD(do_purge);
ACMD(do_weaken);
ACMD(do_item_purge);
ACMD(do_state);
ACMD(do_notice);
ACMD(do_map_notice);
ACMD(do_big_notice);
ACMD(do_who);
ACMD(do_user);
ACMD(do_disconnect);
ACMD(do_kill);
ACMD(do_emotion_allow);
ACMD(do_emotion);
ACMD(do_transfer);
ACMD(do_set);
ACMD(do_cmd);
ACMD(do_reset);
ACMD(do_greset);
ACMD(do_mount);
ACMD(do_fishing);
ACMD(do_refine_rod);
// REFINE_PICK
ACMD(do_max_pick);
ACMD(do_refine_pick);
// END_OF_REFINE_PICK
ACMD(do_fishing_simul);
ACMD(do_console);
ACMD(do_restart);
ACMD(do_advance);
ACMD(do_stat);
ACMD(do_respawn);
ACMD(do_skillup);
ACMD(do_guildskillup);
ACMD(do_pvp);
ACMD(do_point_reset);
ACMD(do_safebox_size);
ACMD(do_safebox_close);
ACMD(do_safebox_password);
ACMD(do_safebox_change_password);
ACMD(do_mall_password);
ACMD(do_mall_close);
ACMD(do_ungroup);
ACMD(do_makeguild);
ACMD(do_deleteguild);
ACMD(do_shutdown);
ACMD(do_group);
ACMD(do_group_random);
ACMD(do_invisibility);
ACMD(do_event_flag);
ACMD(do_get_event_flag);
ACMD(do_private);
ACMD(do_qf);
ACMD(do_clear_quest);
ACMD(do_book);
ACMD(do_reload);
ACMD(do_war);
ACMD(do_nowar);
ACMD(do_setskill);
ACMD(do_setskillother);
ACMD(do_level);
ACMD(do_polymorph);
ACMD(do_polymorph_item);
/*
ACMD(do_b1);
ACMD(do_b2);
ACMD(do_b3);
ACMD(do_b4);
ACMD(do_b5);
ACMD(do_b6);
ACMD(do_b7);
*/
ACMD(do_close_shop);
ACMD(do_set_walk_mode);
ACMD(do_set_run_mode);
ACMD(do_set_skill_group);
ACMD(do_set_skill_point);
ACMD(do_cooltime);
ACMD(do_detaillog);
ACMD(do_monsterlog);
ACMD(do_gwlist);
ACMD(do_stop_guild_war);
ACMD(do_cancel_guild_war);
ACMD(do_guild_state);
ACMD(do_pkmode);
ACMD(do_mobile);
ACMD(do_mobile_auth);
ACMD(do_messenger_auth);
ACMD(do_getqf);
ACMD(do_setqf);
ACMD(do_delqf);
ACMD(do_set_state);
ACMD(do_forgetme);
ACMD(do_aggregate);
ACMD(do_attract_ranger);
ACMD(do_pull_monster);
ACMD(do_setblockmode);
ACMD(do_priv_empire);
ACMD(do_priv_guild);
ACMD(do_mount_test);
ACMD(do_unmount);
ACMD(do_observer);
ACMD(do_observer_exit);
ACMD(do_socket_item);
ACMD(do_xmas);
ACMD(do_stat_minus);
ACMD(do_stat_reset);
ACMD(do_view_equip);
ACMD(do_block_chat);
ACMD(do_vote_block_chat);
// BLOCK_CHAT
ACMD(do_block_chat_list);
// END_OF_BLOCK_CHAT
ACMD(do_party_request);
ACMD(do_party_request_deny);
ACMD(do_party_request_accept);
ACMD(do_build);
ACMD(do_clear_land);
ACMD(do_horse_state);
ACMD(do_horse_level);
ACMD(do_horse_ride);
ACMD(do_horse_summon);
ACMD(do_horse_unsummon);
ACMD(do_horse_set_stat);
ACMD(do_save_attribute_to_image);
ACMD(do_affect_remove);
ACMD(do_change_attr);
ACMD(do_add_attr);
ACMD(do_add_socket);
ACMD(do_inputall)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD>ɾ <20><><EFBFBD><EFBFBD> <20>Է<EFBFBD><D4B7>ϼ<EFBFBD><CFBC><EFBFBD>."));
}
ACMD(do_show_arena_list);
ACMD(do_end_all_duel);
ACMD(do_end_duel);
ACMD(do_duel);
ACMD(do_stat_plus_amount);
ACMD(do_break_marriage);
ACMD(do_oxevent_show_quiz);
ACMD(do_oxevent_log);
ACMD(do_oxevent_get_attender);
ACMD(do_effect);
ACMD(do_threeway_war_info );
ACMD(do_threeway_war_myinfo );
//
//<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ACMD(do_monarch_warpto);
ACMD(do_monarch_transfer);
ACMD(do_monarch_info);
ACMD(do_elect);
ACMD(do_monarch_tax);
ACMD(do_monarch_mob);
ACMD(do_monarch_notice);
//<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
ACMD(do_rmcandidacy);
ACMD(do_setmonarch);
ACMD(do_rmmonarch);
ACMD(do_hair);
//gift notify quest command
ACMD(do_gift);
// ť<><C5A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ACMD(do_inventory);
ACMD(do_cube);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ACMD(do_siege);
ACMD(do_temp);
ACMD(do_frog);
ACMD(do_check_monarch_money);
ACMD(do_reset_subskill );
ACMD(do_flush);
ACMD(do_eclipse);
ACMD(do_weeklyevent);
ACMD(do_event_helper);
ACMD(do_in_game_mall);
ACMD(do_get_mob_count);
ACMD(do_dice);
ACMD(do_special_item);
ACMD(do_click_mall);
ACMD(do_ride);
ACMD(do_get_item_id_list);
ACMD(do_set_socket);
#ifdef __AUCTION__
// temp_auction <20>ӽ<EFBFBD>
ACMD(do_get_auction_list);
ACMD (do_get_my_auction_list);
ACMD (do_get_my_purchase_list);
ACMD(do_get_item_id_list);
ACMD(do_enroll_auction);
ACMD (do_auction_bid);
ACMD (do_auction_impur);
ACMD (do_enroll_wish);
ACMD (do_enroll_sale);
ACMD (do_get_auctioned_item);
ACMD (do_buy_sold_item);
ACMD (do_cancel_auction);
ACMD (do_cancel_wish);
ACMD (do_cancel_sale);
ACMD (do_rebid);
ACMD (do_bid_cancel);
#endif
// <20>ڽ<EFBFBD><DABD><EFBFBD> <20><><EFBFBD>º<EFBFBD><C2BA><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>
ACMD(do_costume);
ACMD(do_set_stat);
// <20><><EFBFBD><EFBFBD>
ACMD (do_can_dead);
ACMD (do_full_set);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ְ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ACMD (do_item_full_set);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ְ<EFBFBD> <20>ɼ<EFBFBD><C9BC><EFBFBD> <20>Ӽ<EFBFBD> <20><><EFBFBD><EFBFBD>
ACMD (do_attr_full_set);
// <20><><EFBFBD><EFBFBD> <20><>ų <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ACMD (do_all_skill_master);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. icon<6F><6E> <20><><EFBFBD><EFBFBD> Ŭ<>󿡼<EFBFBD> Ȯ<><C8AE> <20><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
ACMD (do_use_item);
ACMD (do_dragon_soul);
ACMD (do_ds_list);
ACMD (do_clear_affect);
struct command_info cmd_info[] =
{
{ "!RESERVED!", NULL, 0, POS_DEAD, GM_IMPLEMENTOR }, /* <20>ݵ<EFBFBD><DDB5><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD>̾<EFBFBD><CCBE><EFBFBD> <20>Ѵ<EFBFBD>. */
{ "who", do_who, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "war", do_war, 0, POS_DEAD, GM_PLAYER },
{ "warp", do_warp, 0, POS_DEAD, GM_LOW_WIZARD },
{ "user", do_user, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "notice", do_notice, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "notice_map", do_map_notice, 0, POS_DEAD, GM_LOW_WIZARD },
{ "big_notice", do_big_notice, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "nowar", do_nowar, 0, POS_DEAD, GM_PLAYER },
{ "purge", do_purge, 0, POS_DEAD, GM_WIZARD },
{ "weaken", do_weaken, 0, POS_DEAD, GM_GOD },
{ "dc", do_disconnect, 0, POS_DEAD, GM_LOW_WIZARD },
{ "transfer", do_transfer, 0, POS_DEAD, GM_LOW_WIZARD },
{ "goto", do_goto, 0, POS_DEAD, GM_LOW_WIZARD },
{ "level", do_level, 0, POS_DEAD, GM_LOW_WIZARD },
{ "eventflag", do_event_flag, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "geteventflag", do_get_event_flag, 0, POS_DEAD, GM_LOW_WIZARD },
{ "item", do_item, 0, POS_DEAD, GM_GOD },
{ "mob", do_mob, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "mob_ld", do_mob_ld, 0, POS_DEAD, GM_HIGH_WIZARD }, /* <20><><EFBFBD><EFBFBD> <20><>ġ<EFBFBD><C4A1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ /mob_ld vnum x y dir */
{ "ma", do_mob_aggresive, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "mc", do_mob_coward, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "mm", do_mob_map, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "kill", do_kill, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "ipurge", do_item_purge, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "group", do_group, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "grrandom", do_group_random, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "set", do_set, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "reset", do_reset, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "greset", do_greset, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "advance", do_advance, 0, POS_DEAD, GM_GOD },
{ "book", do_book, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "console", do_console, 0, POS_DEAD, GM_LOW_WIZARD },
{ "shutdow", do_inputall, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "shutdown", do_shutdown, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "stat", do_stat, 0, POS_DEAD, GM_PLAYER },
{ "stat-", do_stat_minus, 0, POS_DEAD, GM_PLAYER },
{ "stat_reset", do_stat_reset, 0, POS_DEAD, GM_LOW_WIZARD },
{ "state", do_state, 0, POS_DEAD, GM_LOW_WIZARD },
// ADD_COMMAND_SLOW_STUN
{ "stun", do_stun, 0, POS_DEAD, GM_LOW_WIZARD },
{ "slow", do_slow, 0, POS_DEAD, GM_LOW_WIZARD },
// END_OF_ADD_COMMAND_SLOW_STUN
{ "respawn", do_respawn, 0, POS_DEAD, GM_WIZARD },
{ "makeguild", do_makeguild, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "deleteguild", do_deleteguild, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "mount", do_mount, 0, POS_MOUNTING, GM_PLAYER },
{ "restart_here", do_restart, SCMD_RESTART_HERE, POS_DEAD, GM_PLAYER },
{ "restart_town", do_restart, SCMD_RESTART_TOWN, POS_DEAD, GM_PLAYER },
{ "phase_selec", do_inputall, 0, POS_DEAD, GM_PLAYER },
{ "phase_select", do_cmd, SCMD_PHASE_SELECT, POS_DEAD, GM_PLAYER },
{ "qui", do_inputall, 0, POS_DEAD, GM_PLAYER },
{ "quit", do_cmd, SCMD_QUIT, POS_DEAD, GM_PLAYER },
{ "logou", do_inputall, 0, POS_DEAD, GM_PLAYER },
{ "logout", do_cmd, SCMD_LOGOUT, POS_DEAD, GM_PLAYER },
{ "skillup", do_skillup, 0, POS_DEAD, GM_PLAYER },
{ "gskillup", do_guildskillup, 0, POS_DEAD, GM_PLAYER },
{ "pvp", do_pvp, 0, POS_DEAD, GM_PLAYER },
{ "safebox", do_safebox_size, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "safebox_close", do_safebox_close, 0, POS_DEAD, GM_PLAYER },
{ "safebox_passwor",do_inputall, 0, POS_DEAD, GM_PLAYER },
{ "safebox_password",do_safebox_password, 0, POS_DEAD, GM_PLAYER },
{ "safebox_change_passwor", do_inputall, 0, POS_DEAD, GM_PLAYER },
{ "safebox_change_password", do_safebox_change_password, 0, POS_DEAD, GM_PLAYER },
{ "mall_passwor", do_inputall, 0, POS_DEAD, GM_PLAYER },
{ "mall_password", do_mall_password, 0, POS_DEAD, GM_PLAYER },
{ "mall_close", do_mall_close, 0, POS_DEAD, GM_PLAYER },
// Group Command
{ "ungroup", do_ungroup, 0, POS_DEAD, GM_PLAYER },
// REFINE_ROD_HACK_BUG_FIX
{ "refine_rod", do_refine_rod, 0, POS_DEAD, GM_IMPLEMENTOR },
// END_OF_REFINE_ROD_HACK_BUG_FIX
// REFINE_PICK
{ "refine_pick", do_refine_pick, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "max_pick", do_max_pick, 0, POS_DEAD, GM_IMPLEMENTOR },
// END_OF_REFINE_PICK
{ "fish_simul", do_fishing_simul, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "invisible", do_invisibility, 0, POS_DEAD, GM_LOW_WIZARD },
{ "qf", do_qf, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "clear_quest", do_clear_quest, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "close_shop", do_close_shop, 0, POS_DEAD, GM_PLAYER },
{ "set_walk_mode", do_set_walk_mode, 0, POS_DEAD, GM_PLAYER },
{ "set_run_mode", do_set_run_mode, 0, POS_DEAD, GM_PLAYER },
{ "setjob",do_set_skill_group, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "setskill", do_setskill, 0, POS_DEAD, GM_LOW_WIZARD },
{ "setskillother", do_setskillother, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "setskillpoint", do_set_skill_point, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "reload", do_reload, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "cooltime", do_cooltime, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "gwlist", do_gwlist, 0, POS_DEAD, GM_LOW_WIZARD },
{ "gwstop", do_stop_guild_war, 0, POS_DEAD, GM_LOW_WIZARD },
{ "gwcancel", do_cancel_guild_war, 0, POS_DEAD, GM_LOW_WIZARD },
{ "gstate", do_guild_state, 0, POS_DEAD, GM_LOW_WIZARD },
{ "pkmode", do_pkmode, 0, POS_DEAD, GM_PLAYER },
{ "messenger_auth", do_messenger_auth, 0, POS_DEAD, GM_PLAYER },
{ "getqf", do_getqf, 0, POS_DEAD, GM_LOW_WIZARD },
{ "setqf", do_setqf, 0, POS_DEAD, GM_LOW_WIZARD },
{ "delqf", do_delqf, 0, POS_DEAD, GM_LOW_WIZARD },
{ "set_state", do_set_state, 0, POS_DEAD, GM_LOW_WIZARD },
{ "<EFBFBD>α׸<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", do_detaillog, 0, POS_DEAD, GM_LOW_WIZARD },
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", do_monsterlog, 0, POS_DEAD, GM_LOW_WIZARD },
{ "detaillog", do_detaillog, 0, POS_DEAD, GM_LOW_WIZARD },
{ "monsterlog", do_monsterlog, 0, POS_DEAD, GM_LOW_WIZARD },
{ "forgetme", do_forgetme, 0, POS_DEAD, GM_LOW_WIZARD },
{ "aggregate", do_aggregate, 0, POS_DEAD, GM_LOW_WIZARD },
{ "attract_ranger", do_attract_ranger, 0, POS_DEAD, GM_LOW_WIZARD },
{ "pull_monster", do_pull_monster, 0, POS_DEAD, GM_LOW_WIZARD },
{ "setblockmode", do_setblockmode, 0, POS_DEAD, GM_PLAYER },
{ "polymorph", do_polymorph, 0, POS_DEAD, GM_LOW_WIZARD },
{ "polyitem", do_polymorph_item, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "priv_empire", do_priv_empire, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "priv_guild", do_priv_guild, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "mount_test", do_mount_test, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "unmount", do_unmount, 0, POS_DEAD, GM_PLAYER },
{ "private", do_private, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "party_request", do_party_request, 0, POS_DEAD, GM_PLAYER },
{ "party_request_accept", do_party_request_accept,0, POS_DEAD, GM_PLAYER },
{ "party_request_deny", do_party_request_deny,0, POS_DEAD, GM_PLAYER },
{ "observer", do_observer, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "observer_exit", do_observer_exit, 0, POS_DEAD, GM_PLAYER },
{ "socketitem", do_socket_item, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "saveati", do_save_attribute_to_image, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "xmas_boom", do_xmas, SCMD_XMAS_BOOM, POS_DEAD, GM_HIGH_WIZARD },
{ "xmas_snow", do_xmas, SCMD_XMAS_SNOW, POS_DEAD, GM_HIGH_WIZARD },
{ "xmas_santa", do_xmas, SCMD_XMAS_SANTA, POS_DEAD, GM_HIGH_WIZARD },
{ "view_equip", do_view_equip, 0, POS_DEAD, GM_PLAYER },
{ "jy", do_block_chat, 0, POS_DEAD, GM_HIGH_WIZARD },
// BLOCK_CHAT
{ "vote_block_chat", do_vote_block_chat, 0, POS_DEAD, GM_PLAYER },
{ "block_chat", do_block_chat, 0, POS_DEAD, GM_PLAYER },
{ "block_chat_list",do_block_chat_list, 0, POS_DEAD, GM_PLAYER },
// END_OF_BLOCK_CHAT
{ "build", do_build, 0, POS_DEAD, GM_PLAYER },
{ "clear_land", do_clear_land, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "affect_remove", do_affect_remove, 0, POS_DEAD, GM_LOW_WIZARD },
{ "horse_state", do_horse_state, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "horse_level", do_horse_level, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "horse_ride", do_horse_ride, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "horse_summon", do_horse_summon, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "horse_unsummon", do_horse_unsummon, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "horse_set_stat", do_horse_set_stat, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "pcbang_update", do_pcbang_update, 0, POS_DEAD, GM_LOW_WIZARD },
{ "pcbang_check", do_pcbang_check, 0, POS_DEAD, GM_LOW_WIZARD },
{ "emotion_allow", do_emotion_allow, 0, POS_FIGHTING, GM_PLAYER },
{ "kiss", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "slap", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "french_kiss", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "clap", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "cheer1", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "cheer2", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
// DANCE
{ "dance1", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "dance2", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "dance3", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "dance4", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "dance5", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "dance6", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
// END_OF_DANCE
{ "congratulation", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "forgive", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "angry", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "attractive", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "sad", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "shy", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "cheerup", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "banter", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "joy", do_emotion, 0, POS_FIGHTING, GM_PLAYER },
{ "change_attr", do_change_attr, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "add_attr", do_add_attr, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "add_socket", do_add_socket, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "user_horse_ride", do_user_horse_ride, 0, POS_FISHING, GM_PLAYER },
{ "user_horse_back", do_user_horse_back, 0, POS_FISHING, GM_PLAYER },
{ "user_horse_feed", do_user_horse_feed, 0, POS_FISHING, GM_PLAYER },
{ "show_arena_list", do_show_arena_list, 0, POS_DEAD, GM_LOW_WIZARD },
{ "end_all_duel", do_end_all_duel, 0, POS_DEAD, GM_LOW_WIZARD },
{ "end_duel", do_end_duel, 0, POS_DEAD, GM_LOW_WIZARD },
{ "duel", do_duel, 0, POS_DEAD, GM_LOW_WIZARD },
{ "con+", do_stat_plus_amount, POINT_HT, POS_DEAD, GM_LOW_WIZARD },
{ "int+", do_stat_plus_amount, POINT_IQ, POS_DEAD, GM_LOW_WIZARD },
{ "str+", do_stat_plus_amount, POINT_ST, POS_DEAD, GM_LOW_WIZARD },
{ "dex+", do_stat_plus_amount, POINT_DX, POS_DEAD, GM_LOW_WIZARD },
{ "break_marriage", do_break_marriage, 0, POS_DEAD, GM_LOW_WIZARD },
{ "show_quiz", do_oxevent_show_quiz, 0, POS_DEAD, GM_LOW_WIZARD },
{ "log_oxevent", do_oxevent_log, 0, POS_DEAD, GM_LOW_WIZARD },
{ "get_oxevent_att", do_oxevent_get_attender,0, POS_DEAD, GM_LOW_WIZARD },
{ "effect", do_effect, 0, POS_DEAD, GM_LOW_WIZARD },
{ "threeway_info", do_threeway_war_info, 0, POS_DEAD, GM_LOW_WIZARD},
{ "threeway_myinfo", do_threeway_war_myinfo, 0, POS_DEAD, GM_LOW_WIZARD},
{ "mto", do_monarch_warpto, 0, POS_DEAD, GM_PLAYER},
{ "mtr", do_monarch_transfer, 0, POS_DEAD, GM_PLAYER},
{ "minfo", do_monarch_info, 0, POS_DEAD, GM_PLAYER},
{ "mtax", do_monarch_tax, 0, POS_DEAD, GM_PLAYER},
{ "mmob", do_monarch_mob, 0, POS_DEAD, GM_PLAYER},
{ "elect", do_elect, 0, POS_DEAD, GM_HIGH_WIZARD},
{ "rmcandidacy", do_rmcandidacy, 0, POS_DEAD, GM_LOW_WIZARD},
{ "setmonarch", do_setmonarch, 0, POS_DEAD, GM_LOW_WIZARD},
{ "rmmonarch", do_rmmonarch, 0, POS_DEAD, GM_LOW_WIZARD},
{ "hair", do_hair, 0, POS_DEAD, GM_PLAYER },
{ "inventory", do_inventory, 0, POS_DEAD, GM_LOW_WIZARD },
{ "cube", do_cube, 0, POS_DEAD, GM_PLAYER },
{ "siege", do_siege, 0, POS_DEAD, GM_LOW_WIZARD },
{ "temp", do_temp, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "frog", do_frog, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "check_mmoney", do_check_monarch_money, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "reset_subskill", do_reset_subskill, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "flush", do_flush, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "gift", do_gift, 0, POS_DEAD, GM_PLAYER }, //gift
{ "mnotice", do_monarch_notice, 0, POS_DEAD, GM_PLAYER },
{ "eclipse", do_eclipse, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "weeklyevent", do_weeklyevent, 0, POS_DEAD, GM_LOW_WIZARD },
{ "eventhelper", do_event_helper, 0, POS_DEAD, GM_HIGH_WIZARD },
{ "in_game_mall", do_in_game_mall, 0, POS_DEAD, GM_PLAYER },
{ "get_mob_count", do_get_mob_count, 0, POS_DEAD, GM_LOW_WIZARD },
{ "dice", do_dice, 0, POS_DEAD, GM_PLAYER },
{ "<EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD>", do_dice, 0, POS_DEAD, GM_PLAYER },
{ "special_item", do_special_item, 0, POS_DEAD, GM_IMPLEMENTOR },
{ "click_mall", do_click_mall, 0, POS_DEAD, GM_PLAYER },
{ "ride", do_ride, 0, POS_DEAD, GM_PLAYER },
{ "item_id_list", do_get_item_id_list, 0, POS_DEAD, GM_LOW_WIZARD },
{ "set_socket", do_set_socket, 0, POS_DEAD, GM_LOW_WIZARD },
#ifdef __AUCTION__
// auction <20>ӽ<EFBFBD>
{ "auction_list", do_get_auction_list, 0, POS_DEAD, GM_PLAYER },
{ "my_auction_list", do_get_my_auction_list, 0, POS_DEAD, GM_PLAYER },
{ "my_purchase_list", do_get_my_purchase_list, 0, POS_DEAD, GM_PLAYER },
{ "enroll_auction", do_enroll_auction, 0, POS_DEAD, GM_PLAYER },
{ "bid", do_auction_bid, 0, POS_DEAD, GM_PLAYER },
{ "impur", do_auction_impur, 0, POS_DEAD, GM_PLAYER },
{ "enroll_wish", do_enroll_wish, 0, POS_DEAD, GM_PLAYER },
{ "enroll_sale", do_enroll_sale, 0, POS_DEAD, GM_PLAYER },
{ "get_auctioned_item", do_get_auctioned_item, 0, POS_DEAD, GM_PLAYER },
{ "buy_sold_item", do_buy_sold_item, 0, POS_DEAD, GM_PLAYER },
{ "cancel_auction", do_cancel_auction, 0, POS_DEAD, GM_PLAYER },
{ "cancel_wish", do_cancel_wish, 0, POS_DEAD, GM_PLAYER },
{ "cancel_sale", do_cancel_sale, 0, POS_DEAD, GM_PLAYER },
{ "rebid", do_rebid, 0, POS_DEAD, GM_PLAYER },
{ "bid_cancel", do_bid_cancel, 0, POS_DEAD, GM_PLAYER },
#endif
{ "costume", do_costume, 0, POS_DEAD, GM_PLAYER },
{ "tcon", do_set_stat, POINT_HT, POS_DEAD, GM_LOW_WIZARD },
{ "tint", do_set_stat, POINT_IQ, POS_DEAD, GM_LOW_WIZARD },
{ "tstr", do_set_stat, POINT_ST, POS_DEAD, GM_LOW_WIZARD },
{ "tdex", do_set_stat, POINT_DX, POS_DEAD, GM_LOW_WIZARD },
{ "cannot_dead", do_can_dead, 1, POS_DEAD, GM_LOW_WIZARD},
{ "can_dead", do_can_dead, 0, POS_DEAD, GM_LOW_WIZARD},
{ "full_set", do_full_set, 0, POS_DEAD, GM_LOW_WIZARD},
{ "item_full_set", do_item_full_set, 0, POS_DEAD, GM_LOW_WIZARD},
{ "attr_full_set", do_attr_full_set, 0, POS_DEAD, GM_LOW_WIZARD},
{ "all_skill_master", do_all_skill_master, 0, POS_DEAD, GM_LOW_WIZARD},
{ "use_item", do_use_item, 0, POS_DEAD, GM_LOW_WIZARD},
{ "dragon_soul", do_dragon_soul, 0, POS_DEAD, GM_PLAYER },
{ "ds_list", do_ds_list, 0, POS_DEAD, GM_PLAYER },
{ "do_clear_affect", do_clear_affect, 0, POS_DEAD, GM_LOW_WIZARD},
{ "\n", NULL, 0, POS_DEAD, GM_IMPLEMENTOR } /* <20>ݵ<EFBFBD><DDB5><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̾<EFBFBD><CCBE><EFBFBD> <20>Ѵ<EFBFBD>. */
};
void interpreter_set_privilege(const char *cmd, int lvl)
{
int i;
for (i = 0; *cmd_info[i].command != '\n'; ++i)
{
if (!str_cmp(cmd, cmd_info[i].command))
{
cmd_info[i].gm_level = lvl;
sys_log(0, "Setting command privilege: %s -> %d", cmd, lvl);
break;
}
}
}
void double_dollar(const char *src, size_t src_len, char *dest, size_t dest_len)
{
const char * tmp = src;
size_t cur_len = 0;
// \0 <20><><EFBFBD><EFBFBD> <20>ڸ<EFBFBD> Ȯ<><C8AE>
dest_len -= 1;
while (src_len-- && *tmp)
{
if (*tmp == '$')
{
if (cur_len + 1 >= dest_len)
break;
*(dest++) = '$';
*(dest++) = *(tmp++);
cur_len += 2;
}
else
{
if (cur_len >= dest_len)
break;
*(dest++) = *(tmp++);
cur_len += 1;
}
}
*dest = '\0';
}
void interpret_command(LPCHARACTER ch, const char * argument, size_t len)
{
if (NULL == ch)
{
sys_err ("NULL CHRACTER");
return ;
}
char cmd[128 + 1]; // buffer overflow <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʵ<EFBFBD><CAB5><EFBFBD> <20>Ϻη<CFBA> <20><><EFBFBD≯<EFBFBD> ª<><C2AA> <20><><EFBFBD><EFBFBD>
char new_line[256 + 1];
const char * line;
int icmd;
if (len == 0 || !*argument)
return;
double_dollar(argument, len, new_line, sizeof(new_line));
size_t cmdlen;
line = first_cmd(new_line, cmd, sizeof(cmd), &cmdlen);
for (icmd = 1; *cmd_info[icmd].command != '\n'; ++icmd)
{
if (cmd_info[icmd].command_pointer == do_cmd)
{
if (!strcmp(cmd_info[icmd].command, cmd)) // do_cmd<6D><64> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ɾ <20>ľ<EFBFBD> <20><> <20><> <20>ִ<EFBFBD>.
break;
}
else if (!strncmp(cmd_info[icmd].command, cmd, cmdlen))
break;
}
if (ch->GetPosition() < cmd_info[icmd].minimum_position)
{
switch (ch->GetPosition())
{
case POS_MOUNTING:
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ź <20><><EFBFBD>¿<EFBFBD><C2BF><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
break;
case POS_DEAD:
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>¿<EFBFBD><C2BF><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
break;
case POS_SLEEPING:
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD>޼ӿ<EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD>Կ<EFBFBD>?"));
break;
case POS_RESTING:
case POS_SITTING:
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ͼ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>."));
break;
/*
case POS_FIGHTING:
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ɰ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20>Դϴ<D4B4>. <20><><EFBFBD><EFBFBD> <20>ϼ<EFBFBD><CFBC><EFBFBD>."));
break;
*/
default:
sys_err("unknown position %d", ch->GetPosition());
break;
}
return;
}
if (*cmd_info[icmd].command == '\n')
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD>׷<EFBFBD> <20><><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>"));
return;
}
if (cmd_info[icmd].gm_level && cmd_info[icmd].gm_level > ch->GetGMLevel())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD>׷<EFBFBD> <20><><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>"));
return;
}
if (strncmp("phase", cmd_info[icmd].command, 5) != 0) // <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ɾ<EFBFBD> ó<><C3B3>
sys_log(0, "COMMAND: %s: %s", ch->GetName(), cmd_info[icmd].command);
((*cmd_info[icmd].command_pointer) (ch, line, icmd, cmd_info[icmd].subcmd));
if (ch->GetGMLevel() >= GM_LOW_WIZARD)
{
if (cmd_info[icmd].gm_level >= GM_LOW_WIZARD)
{
if (LC_IsEurope() == true || /*LC_IsNewCIBN() == true || */LC_IsCanada() == true || LC_IsBrazil() == true || LC_IsSingapore() == true )
{
char buf[1024];
snprintf( buf, sizeof(buf), "%s", argument );
LogManager::instance().GMCommandLog(ch->GetPlayerID(), ch->GetName(), ch->GetDesc()->GetHostName(), g_bChannel, buf);
}
}
}
}

69
game/src/cmd.h Normal file
View File

@ -0,0 +1,69 @@
#ifndef __INC_METIN_II_GAME_CMD_H__
#define __INC_METIN_II_GAME_CMD_H__
#define ACMD(name) void (name)(LPCHARACTER ch, const char *argument, int cmd, int subcmd)
#define CMD_NAME(name) cmd_info[cmd].command
struct command_info
{
const char * command;
void (*command_pointer) (LPCHARACTER ch, const char *argument, int cmd, int subcmd);
int subcmd;
int minimum_position;
int gm_level;
};
extern struct command_info cmd_info[];
extern void interpret_command(LPCHARACTER ch, const char * argument, size_t len);
extern void interpreter_set_privilege(const char * cmd, int lvl);
enum SCMD_ACTION
{
SCMD_SLAP,
SCMD_KISS,
SCMD_FRENCH_KISS,
SCMD_HUG,
SCMD_LONG_HUG,
SCMD_SHOLDER,
SCMD_FOLD_ARM
};
enum SCMD_CMD
{
SCMD_LOGOUT,
SCMD_QUIT,
SCMD_PHASE_SELECT,
SCMD_SHUTDOWN,
};
enum SCMD_RESTART
{
SCMD_RESTART_TOWN,
SCMD_RESTART_HERE
};
enum SCMD_XMAS
{
SCMD_XMAS_BOOM,
SCMD_XMAS_SNOW,
SCMD_XMAS_SANTA,
};
extern void Shutdown(int iSec);
extern void SendNotice(const char * c_pszBuf); // <20><> <20><><EFBFBD>Ӽ<EFBFBD><D3BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
extern void SendLog(const char * c_pszBuf); // <20><EFBFBD>ڿ<EFBFBD><DABF>Ը<EFBFBD> <20><><EFBFBD><EFBFBD>
extern void BroadcastNotice(const char * c_pszBuf); // <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
extern void SendNoticeMap(const char* c_pszBuf, int nMapIndex, bool bBigFont); // <20><><EFBFBD><EFBFBD> <20>ʿ<EFBFBD><CABF><EFBFBD> <20><><EFBFBD><EFBFBD>
extern void SendMonarchNotice(BYTE bEmpire, const char * c_pszBuf); // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// LUA_ADD_BGM_INFO
void CHARACTER_SetBGMVolumeEnable();
void CHARACTER_AddBGMInfo(unsigned mapIndex, const char* name, float vol);
// END_OF_LUA_ADD_BGM_INFO
// LUA_ADD_GOTO_INFO
extern void CHARACTER_AddGotoInfo(const std::string& c_st_name, BYTE empire, int mapIndex, DWORD x, DWORD y);
// END_OF_LUA_ADD_GOTO_INFO
#endif

267
game/src/cmd_emotion.cpp Normal file
View File

@ -0,0 +1,267 @@
#include "stdafx.h"
#include "utils.h"
#include "char.h"
#include "char_manager.h"
#include "motion.h"
#include "packet.h"
#include "buffer_manager.h"
#include "unique_item.h"
#include "wedding.h"
#define NEED_TARGET (1 << 0)
#define NEED_PC (1 << 1)
#define WOMAN_ONLY (1 << 2)
#define OTHER_SEX_ONLY (1 << 3)
#define SELF_DISARM (1 << 4)
#define TARGET_DISARM (1 << 5)
#define BOTH_DISARM (SELF_DISARM | TARGET_DISARM)
struct emotion_type_s
{
const char * command;
const char * command_to_client;
long flag;
float extra_delay;
} emotion_types[] = {
{ "Ű<EFBFBD><EFBFBD>", "french_kiss", NEED_PC | OTHER_SEX_ONLY | BOTH_DISARM, 2.0f },
{ "<EFBFBD>ǻ<EFBFBD>", "kiss", NEED_PC | OTHER_SEX_ONLY | BOTH_DISARM, 1.5f },
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "slap", NEED_PC | SELF_DISARM, 1.5f },
{ "<EFBFBD>ڼ<EFBFBD>", "clap", 0, 1.0f },
{ "<EFBFBD><EFBFBD>", "cheer1", 0, 1.0f },
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "cheer2", 0, 1.0f },
// DANCE
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>1", "dance1", 0, 1.0f },
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>2", "dance2", 0, 1.0f },
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>3", "dance3", 0, 1.0f },
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>4", "dance4", 0, 1.0f },
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>5", "dance5", 0, 1.0f },
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>6", "dance6", 0, 1.0f },
// END_OF_DANCE
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "congratulation", 0, 1.0f },
{ "<EFBFBD>", "forgive", 0, 1.0f },
{ "ȭ<EFBFBD><EFBFBD>", "angry", 0, 1.0f },
{ "<EFBFBD><EFBFBD>Ȥ", "attractive", 0, 1.0f },
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "sad", 0, 1.0f },
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "shy", 0, 1.0f },
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "cheerup", 0, 1.0f },
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "banter", 0, 1.0f },
{ "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", "joy", 0, 1.0f },
{ "\n", "\n", 0, 0.0f },
/*
//{ "Ű<><C5B0>", NEED_PC | OTHER_SEX_ONLY | BOTH_DISARM, MOTION_ACTION_FRENCH_KISS, 1.0f },
{ "<22>ǻ<EFBFBD>", NEED_PC | OTHER_SEX_ONLY | BOTH_DISARM, MOTION_ACTION_KISS, 1.0f },
{ "<22><><EFBFBD>ȱ<EFBFBD>", NEED_PC | OTHER_SEX_ONLY | BOTH_DISARM, MOTION_ACTION_SHORT_HUG, 1.0f },
{ "<22><><EFBFBD><EFBFBD>", NEED_PC | OTHER_SEX_ONLY | BOTH_DISARM, MOTION_ACTION_LONG_HUG, 1.0f },
{ "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", NEED_PC | SELF_DISARM, MOTION_ACTION_PUT_ARMS_SHOULDER, 0.0f },
{ "<22><>¯", NEED_PC | WOMAN_ONLY | SELF_DISARM, MOTION_ACTION_FOLD_ARM, 0.0f },
{ "<22><><EFBFBD><EFBFBD>", NEED_PC | SELF_DISARM, MOTION_ACTION_SLAP, 1.5f },
{ "<22><><EFBFBD>Ķ<EFBFBD>", 0, MOTION_ACTION_CHEER_01, 0.0f },
{ "<22><><EFBFBD><EFBFBD>", 0, MOTION_ACTION_CHEER_02, 0.0f },
{ "<22>ڼ<EFBFBD>", 0, MOTION_ACTION_CHEER_03, 0.0f },
{ "ȣȣ", 0, MOTION_ACTION_LAUGH_01, 0.0f },
{ "űű", 0, MOTION_ACTION_LAUGH_02, 0.0f },
{ "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_LAUGH_03, 0.0f },
{ "<22><><EFBFBD><EFBFBD>", 0, MOTION_ACTION_CRY_01, 0.0f },
{ "<22><><EFBFBD><EFBFBD>", 0, MOTION_ACTION_CRY_02, 0.0f },
{ "<22>λ<EFBFBD>", 0, MOTION_ACTION_GREETING_01, 0.0f },
{ "<22><><EFBFBD><EFBFBD>", 0, MOTION_ACTION_GREETING_02, 0.0f },
{ "<22><><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD>", 0, MOTION_ACTION_GREETING_03, 0.0f },
{ "<22><><EFBFBD><EFBFBD>", 0, MOTION_ACTION_INSULT_01, 0.0f },
{ "<22><><EFBFBD><EFBFBD>", SELF_DISARM, MOTION_ACTION_INSULT_02, 0.0f },
{ "<22><><EFBFBD><EFBFBD>", 0, MOTION_ACTION_INSULT_03, 0.0f },
{ "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_ETC_01, 0.0f },
{ "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_ETC_02, 0.0f },
{ "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_ETC_03, 0.0f },
{ "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 0, MOTION_ACTION_ETC_04, 0.0f },
{ "ơ", 0, MOTION_ACTION_ETC_05, 0.0f },
{ "<22><>", 0, MOTION_ACTION_ETC_06, 0.0f },
*/
};
std::set<std::pair<DWORD, DWORD> > s_emotion_set;
ACMD(do_emotion_allow)
{
if ( ch->GetArena() )
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ͻ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
return;
}
char arg1[256];
one_argument(argument, arg1, sizeof(arg1));
if (!*arg1)
return;
DWORD val = 0; str_to_number(val, arg1);
s_emotion_set.insert(std::make_pair(ch->GetVID(), val));
}
bool CHARACTER_CanEmotion(CHARACTER& rch)
{
// <20><>ȥ<EFBFBD><C8A5> <20>ʿ<EFBFBD><CABF><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD>.
if (marriage::WeddingManager::instance().IsWeddingMap(rch.GetMapIndex()))
return true;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD>.
if (rch.IsEquipUniqueItem(UNIQUE_ITEM_EMOTION_MASK))
return true;
if (rch.IsEquipUniqueItem(UNIQUE_ITEM_EMOTION_MASK2))
return true;
return false;
}
ACMD(do_emotion)
{
int i;
{
if (ch->IsRiding())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> ź <20><><EFBFBD>¿<EFBFBD><C2BF><EFBFBD> <20><><EFBFBD><EFBFBD>ǥ<EFBFBD><C7A5><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
return;
}
}
for (i = 0; *emotion_types[i].command != '\n'; ++i)
{
if (!strcmp(cmd_info[cmd].command, emotion_types[i].command))
break;
if (!strcmp(cmd_info[cmd].command, emotion_types[i].command_to_client))
break;
}
if (*emotion_types[i].command == '\n')
{
sys_err("cannot find emotion");
return;
}
if (!CHARACTER_CanEmotion(*ch))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD> <20><> <20><> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>."));
return;
}
if (IS_SET(emotion_types[i].flag, WOMAN_ONLY) && SEX_MALE==GET_SEX(ch))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD> <20><> <20><> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>."));
return;
}
char arg1[256];
one_argument(argument, arg1, sizeof(arg1));
LPCHARACTER victim = NULL;
if (*arg1)
victim = ch->FindCharacterInView(arg1, IS_SET(emotion_types[i].flag, NEED_PC));
if (IS_SET(emotion_types[i].flag, NEED_TARGET | NEED_PC))
{
if (!victim)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD>׷<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
return;
}
}
if (victim)
{
if (!victim->IsPC() || victim == ch)
return;
if (victim->IsRiding())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> ź <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ǥ<EFBFBD><C7A5><EFBFBD><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
return;
}
long distance = DISTANCE_APPROX(ch->GetX() - victim->GetX(), ch->GetY() - victim->GetY());
if (distance < 10)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD>ʹ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>."));
return;
}
if (distance > 500)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD>ʹ<EFBFBD> <20>ָ<EFBFBD> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>"));
return;
}
if (IS_SET(emotion_types[i].flag, OTHER_SEX_ONLY))
{
if (GET_SEX(ch)==GET_SEX(victim))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD>̼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>."));
return;
}
}
if (IS_SET(emotion_types[i].flag, NEED_PC))
{
if (s_emotion_set.find(std::make_pair(victim->GetVID(), ch->GetVID())) == s_emotion_set.end())
{
if (true == marriage::CManager::instance().IsMarried( ch->GetPlayerID() ))
{
const marriage::TMarriage* marriageInfo = marriage::CManager::instance().Get( ch->GetPlayerID() );
const DWORD other = marriageInfo->GetOther( ch->GetPlayerID() );
if (0 == other || other != victim->GetPlayerID())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD> <20>ൿ<EFBFBD><E0B5BF> <20><>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD> <20>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>մϴ<D5B4>."));
return;
}
}
else
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD> <20>ൿ<EFBFBD><E0B5BF> <20><>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD> <20>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>մϴ<D5B4>."));
return;
}
}
s_emotion_set.insert(std::make_pair(ch->GetVID(), victim->GetVID()));
}
}
char chatbuf[256+1];
int len = snprintf(chatbuf, sizeof(chatbuf), "%s %u %u",
emotion_types[i].command_to_client,
(DWORD) ch->GetVID(), victim ? (DWORD) victim->GetVID() : 0);
if (len < 0 || len >= (int) sizeof(chatbuf))
len = sizeof(chatbuf) - 1;
++len; // \0 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
TPacketGCChat pack_chat;
pack_chat.header = HEADER_GC_CHAT;
pack_chat.size = sizeof(TPacketGCChat) + len;
pack_chat.type = CHAT_TYPE_COMMAND;
pack_chat.id = 0;
TEMP_BUFFER buf;
buf.write(&pack_chat, sizeof(TPacketGCChat));
buf.write(chatbuf, len);
ch->PacketAround(buf.read_peek(), buf.size());
if (victim)
sys_log(1, "ACTION: %s TO %s", emotion_types[i].command, victim->GetName());
else
sys_log(1, "ACTION: %s", emotion_types[i].command);
}

2678
game/src/cmd_general.cpp Normal file

File diff suppressed because it is too large Load Diff

4411
game/src/cmd_gm.cpp Normal file

File diff suppressed because it is too large Load Diff

34
game/src/cmd_oxevent.cpp Normal file
View File

@ -0,0 +1,34 @@
#include "stdafx.h"
#include "utils.h"
#include "char.h"
#include "OXEvent.h"
#include "questmanager.h"
#include "questlua.h"
#include "config.h"
#include "locale_service.h"
#include "cmd.h"
ACMD(do_oxevent_show_quiz)
{
ch->ChatPacket(CHAT_TYPE_INFO, "===== OX QUIZ LIST =====");
COXEventManager::instance().ShowQuizList(ch);
ch->ChatPacket(CHAT_TYPE_INFO, "===== OX QUIZ LIST END =====");
}
ACMD(do_oxevent_log)
{
if ( COXEventManager::instance().LogWinner() == false )
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("OX<EFBFBD>̺<EFBFBD>Ʈ<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ο<EFBFBD><CEBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD><EFBFBD>ϴ<EFBFBD>."));
}
else
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("OX<EFBFBD>̺<EFBFBD>Ʈ<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ο<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>߽<EFBFBD><DFBD>ϴ<EFBFBD>."));
}
}
ACMD(do_oxevent_get_attender)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD> : %d"), COXEventManager::instance().GetAttenderCount());
}

1319
game/src/config.cpp Normal file

File diff suppressed because it is too large Load Diff

120
game/src/config.h Normal file
View File

@ -0,0 +1,120 @@
#ifndef __INC_METIN_II_GAME_CONFIG_H__
#define __INC_METIN_II_GAME_CONFIG_H__
enum
{
ADDRESS_MAX_LEN = 15
};
void config_init(const std::string& st_localeServiceName); // default "" is CONFIG
extern char sql_addr[256];
extern WORD mother_port;
extern WORD p2p_port;
extern char db_addr[ADDRESS_MAX_LEN + 1];
extern WORD db_port;
extern char teen_addr[ADDRESS_MAX_LEN + 1];
extern WORD teen_port;
extern char passpod_addr[ADDRESS_MAX_LEN + 1];
extern WORD passpod_port;
extern int passes_per_sec;
extern int save_event_second_cycle;
extern int ping_event_second_cycle;
extern int test_server;
extern bool guild_mark_server;
extern BYTE guild_mark_min_level;
extern bool distribution_test_server;
extern bool china_event_server;
extern bool g_bNoMoreClient;
extern bool g_bNoRegen;
extern bool g_bTrafficProfileOn; ///< true <20≯<EFBFBD> TrafficProfiler <20><> <20>Ҵ<EFBFBD>.
extern BYTE g_bChannel;
extern bool map_allow_find(int index);
extern void map_allow_copy(long * pl, int size);
extern bool no_wander;
extern int g_iUserLimit;
extern time_t g_global_time;
const char * get_table_postfix();
extern std::string g_stHostname;
extern std::string g_stLocale;
extern std::string g_stLocaleFilename;
extern char g_szPublicIP[16];
extern char g_szInternalIP[16];
extern int (*is_twobyte) (const char * str);
extern int (*check_name) (const char * str);
extern bool g_bSkillDisable;
extern int g_iFullUserCount;
extern int g_iBusyUserCount;
extern void LoadStateUserCount();
extern bool g_bEmpireWhisper;
extern BYTE g_bAuthServer;
extern BYTE g_bBilling;
extern BYTE PK_PROTECT_LEVEL;
extern void LoadValidCRCList();
extern bool IsValidProcessCRC(DWORD dwCRC);
extern bool IsValidFileCRC(DWORD dwCRC);
extern std::string g_stAuthMasterIP;
extern WORD g_wAuthMasterPort;
extern std::string g_stClientVersion;
extern bool g_bCheckClientVersion;
extern void CheckClientVersion();
extern std::string g_stQuestDir;
//extern std::string g_stQuestObjectDir;
extern std::set<std::string> g_setQuestObjectDir;
extern std::vector<std::string> g_stAdminPageIP;
extern std::string g_stAdminPagePassword;
extern int SPEEDHACK_LIMIT_COUNT;
extern int SPEEDHACK_LIMIT_BONUS;
extern int g_iSyncHackLimitCount;
extern int g_server_id;
extern std::string g_strWebMallURL;
extern int VIEW_RANGE;
extern int VIEW_BONUS_RANGE;
extern bool g_bCheckMultiHack;
extern bool g_protectNormalPlayer; // <20><><EFBFBD><EFBFBD><EFBFBD>ڰ<EFBFBD> "<22><>ȭ<EFBFBD><C8AD><EFBFBD><EFBFBD>" <20><> <20>Ϲ<EFBFBD><CFB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
extern bool g_noticeBattleZone; // <20>߸<EFBFBD><DFB8><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD> <20>ȳ<EFBFBD><C8B3>޼<EFBFBD><DEBC><EFBFBD><EFBFBD><EFBFBD> <20>˷<EFBFBD><CBB7><EFBFBD>
extern DWORD g_GoldDropTimeLimitValue;
extern bool isHackShieldEnable;
extern int HackShield_FirstCheckWaitTime;
extern int HackShield_CheckCycleTime;
extern bool bXTrapEnabled;
extern int gPlayerMaxLevel;
extern bool g_BlockCharCreation;
#endif /* __INC_METIN_II_GAME_CONFIG_H__ */

1297
game/src/constants.cpp Normal file

File diff suppressed because it is too large Load Diff

190
game/src/constants.h Normal file
View File

@ -0,0 +1,190 @@
#ifndef __INC_METIN_II_GAME_CONSTANTS_H__
#define __INC_METIN_II_GAME_CONSTANTS_H__
#include "../../common/tables.h"
enum EMonsterChatState
{
MONSTER_CHAT_WAIT,
MONSTER_CHAT_ATTACK,
MONSTER_CHAT_CHASE,
MONSTER_CHAT_ATTACKED,
};
typedef struct SMobRankStat
{
int iGoldPercent; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Ȯ<><C8AE>
} TMobRankStat;
typedef struct SMobStat
{
BYTE byLevel;
WORD HP;
DWORD dwExp;
WORD wDefGrade;
} TMobStat;
typedef struct SBattleTypeStat
{
int AttGradeBias;
int DefGradeBias;
int MagicAttGradeBias;
int MagicDefGradeBias;
} TBattleTypeStat;
typedef struct SJobInitialPoints
{
int st, ht, dx, iq;
int max_hp, max_sp;
int hp_per_ht, sp_per_iq;
int hp_per_lv_begin, hp_per_lv_end;
int sp_per_lv_begin, sp_per_lv_end;
int max_stamina;
int stamina_per_con;
int stamina_per_lv_begin, stamina_per_lv_end;
} TJobInitialPoints;
typedef struct __coord
{
int x, y;
} Coord;
typedef struct SApplyInfo
{
BYTE bPointType; // APPLY -> POINT
} TApplyInfo;
enum {
FORTUNE_BIG_LUCK,
FORTUNE_LUCK,
FORTUNE_SMALL_LUCK,
FORTUNE_NORMAL,
FORTUNE_SMALL_BAD_LUCK,
FORTUNE_BAD_LUCK,
FORTUNE_BIG_BAD_LUCK,
FORTUNE_MAX_NUM,
};
const int STONE_INFO_MAX_NUM = 10;
const int STONE_LEVEL_MAX_NUM = 4;
struct SStoneDropInfo
{
DWORD dwMobVnum;
int iDropPct;
int iLevelPct[STONE_LEVEL_MAX_NUM+1];
};
inline bool operator < (const SStoneDropInfo& l, DWORD r)
{
return l.dwMobVnum < r;
}
inline bool operator < (DWORD l, const SStoneDropInfo& r)
{
return l < r.dwMobVnum;
}
inline bool operator < (const SStoneDropInfo& l, const SStoneDropInfo& r)
{
return l.dwMobVnum < r.dwMobVnum;
}
extern const TApplyInfo aApplyInfo[MAX_APPLY_NUM];
extern const TMobRankStat MobRankStats[MOB_RANK_MAX_NUM];
extern TBattleTypeStat BattleTypeStats[BATTLE_TYPE_MAX_NUM];
extern const DWORD party_exp_distribute_table[PLAYER_MAX_LEVEL_CONST + 1];
extern const DWORD exp_table_euckr[PLAYER_EXP_TABLE_MAX + 1];
extern const DWORD exp_table_common[PLAYER_EXP_TABLE_MAX + 1];
extern const DWORD exp_table_newcibn[PLAYER_EXP_TABLE_MAX + 1];
extern const DWORD* exp_table;
extern const DWORD guild_exp_table[GUILD_MAX_LEVEL + 1];
extern const DWORD guild_exp_table2[GUILD_MAX_LEVEL + 1];
#define MAX_EXP_DELTA_OF_LEV 31
#define PERCENT_LVDELTA(me, victim) aiPercentByDeltaLev[MINMAX(0, (victim + 15) - me, MAX_EXP_DELTA_OF_LEV - 1)]
#define PERCENT_LVDELTA_BOSS(me, victim) aiPercentByDeltaLevForBoss[MINMAX(0, (victim + 15) - me, MAX_EXP_DELTA_OF_LEV - 1)]
#define CALCULATE_VALUE_LVDELTA(me, victim, val) ((val * PERCENT_LVDELTA(me, victim)) / 100)
extern const int aiPercentByDeltaLev_euckr[MAX_EXP_DELTA_OF_LEV];
extern const int aiPercentByDeltaLevForBoss_euckr[MAX_EXP_DELTA_OF_LEV];
extern const int * aiPercentByDeltaLev;
extern const int * aiPercentByDeltaLevForBoss;
#define ARROUND_COORD_MAX_NUM 161
extern Coord aArroundCoords[ARROUND_COORD_MAX_NUM];
extern TJobInitialPoints JobInitialPoints[JOB_MAX_NUM];
extern const int aiMobEnchantApplyIdx[MOB_ENCHANTS_MAX_NUM];
extern const int aiMobResistsApplyIdx[MOB_RESISTS_MAX_NUM];
extern const int aSkillAttackAffectProbByRank[MOB_RANK_MAX_NUM];
extern const int aiItemMagicAttributePercentHigh[ITEM_ATTRIBUTE_MAX_LEVEL]; // 1<><31><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
extern const int aiItemMagicAttributePercentLow[ITEM_ATTRIBUTE_MAX_LEVEL];
extern const int aiItemAttributeAddPercent[ITEM_ATTRIBUTE_MAX_NUM];
extern const int aiWeaponSocketQty[WEAPON_NUM_TYPES];
extern const int aiArmorSocketQty[ARMOR_NUM_TYPES];
extern const int aiSocketPercentByQty[5][4];
extern const int aiExpLossPercents[PLAYER_EXP_TABLE_MAX + 1];
extern const int * aiSkillPowerByLevel;
extern const int aiSkillPowerByLevel_euckr[SKILL_MAX_LEVEL + 1];
extern const int aiPolymorphPowerByLevel[SKILL_MAX_LEVEL + 1];
extern const int aiSkillBookCountForLevelUp[10];
extern const int aiGrandMasterSkillBookCountForLevelUp[10];
extern const int aiGrandMasterSkillBookMinCount[10];
extern const int aiGrandMasterSkillBookMaxCount[10];
extern const int CHN_aiPartyBonusExpPercentByMemberCount[9];
extern const int KOR_aiPartyBonusExpPercentByMemberCount[9];
extern const int KOR_aiUniqueItemPartyBonusExpPercentByMemberCount[9];
typedef std::map<DWORD, TItemAttrTable> TItemAttrMap;
extern TItemAttrMap g_map_itemAttr;
extern TItemAttrMap g_map_itemRare;
extern const int * aiChainLightningCountBySkillLevel;
extern const int aiChainLightningCountBySkillLevel_euckr[SKILL_MAX_LEVEL + 1];
extern const char * c_apszEmpireNames[EMPIRE_MAX_NUM];
extern const char * c_apszPrivNames[MAX_PRIV_NUM];
extern const SStoneDropInfo aStoneDrop[STONE_INFO_MAX_NUM];
typedef struct
{
long lMapIndex;
int iWarPrice;
int iWinnerPotionRewardPctToWinner;
int iLoserPotionRewardPctToWinner;
int iInitialScore;
int iEndScore;
} TGuildWarInfo;
extern TGuildWarInfo KOR_aGuildWarInfo[GUILD_WAR_TYPE_MAX_NUM];
// ACCESSORY_REFINE
enum
{
ITEM_ACCESSORY_SOCKET_MAX_NUM = 3
};
extern const int aiAccessorySocketAddPct[ITEM_ACCESSORY_SOCKET_MAX_NUM];
extern const int aiAccessorySocketEffectivePct[ITEM_ACCESSORY_SOCKET_MAX_NUM + 1];
extern const int aiAccessorySocketDegradeTime[ITEM_ACCESSORY_SOCKET_MAX_NUM + 1];
extern const int aiAccessorySocketPutPct[ITEM_ACCESSORY_SOCKET_MAX_NUM + 1];
long FN_get_apply_type(const char *apply_type_string);
// END_OF_ACCESSORY_REFINE
long FN_get_apply_type(const char *apply_type_string);
#endif

136
game/src/crc32.cpp Normal file
View File

@ -0,0 +1,136 @@
#include "stdafx.h"
#include "crc32.h"
static unsigned long CRCTable[256] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
#define DO1(buf, i) crc = CRCTable[(crc ^ buf[i]) & 0xff] ^ (crc >> 8)
#define DO2(buf, i) DO1(buf, i); DO1(buf, i + 1);
#define DO4(buf, i) DO2(buf, i); DO2(buf, i + 2);
#define DO8(buf, i) DO4(buf, i); DO4(buf, i + 4);
#define DO16(buf, i) DO8(buf, i); DO8(buf, i + 8);
crc_t GetCRC32(const char * buf, size_t len)
{
crc_t crc = 0xffffffff;
if (16 <= len)
{
do
{
DO16(buf, 0);
buf += 16;
len -= 16;
} while (len >= 16);
}
if (0 != len)
{
do
{
DO1(buf, 0);
++buf;
--len;
} while (len > 0);
}
crc ^= 0xffffffff;
return crc;
}
#define DO1CI(buf, i) crc = CRCTable[(crc ^ UPPER(buf[i])) & 0xff] ^ (crc >> 8)
#define DO2CI(buf, i) DO1CI(buf, i); DO1CI(buf, i + 1);
#define DO4CI(buf, i) DO2CI(buf, i); DO2CI(buf, i + 2);
#define DO8CI(buf, i) DO4CI(buf, i); DO4CI(buf, i + 4);
#define DO16CI(buf, i) DO8CI(buf, i); DO8CI(buf, i + 8);
crc_t GetCaseCRC32(const char * buf, size_t len)
{
crc_t crc = 0xffffffff;
if (16 <= len)
{
do
{
DO16CI(buf, 0);
buf += 16;
len -= 16;
} while (len >= 16);
}
if (0 != len)
{
do
{
DO1CI(buf, 0);
++buf;
--len;
} while (len > 0);
}
crc ^= 0xffffffff;
return crc;
}
crc_t GetFastHash(const char * key, size_t len)
{
const char * end = key + len;
unsigned long h = 0;
while (key < end)
{
h *= 16777619;
h ^= *(key++);
}
return (h);
}

Some files were not shown because too many files have changed in this diff Show More