Add project files.
This commit is contained in:
56
game/CMakeLists.txt
Normal file
56
game/CMakeLists.txt
Normal 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
335
game/src/BattleArena.cpp
Normal 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
42
game/src/BattleArena.h
Normal 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
197
game/src/BlueDragon.cpp
Normal 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
5
game/src/BlueDragon.h
Normal 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);
|
||||
|
218
game/src/BlueDragon_Binder.cpp
Normal file
218
game/src/BlueDragon_Binder.cpp
Normal 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;
|
||||
}
|
||||
|
13
game/src/BlueDragon_Binder.h
Normal file
13
game/src/BlueDragon_Binder.h
Normal 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
342
game/src/BlueDragon_Skill.h
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
225
game/src/ClientPackageCryptInfo.cpp
Normal file
225
game/src/ClientPackageCryptInfo.cpp
Normal 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;
|
||||
}
|
||||
|
117
game/src/ClientPackageCryptInfo.h
Normal file
117
game/src/ClientPackageCryptInfo.h
Normal 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
255
game/src/DragonLair.cpp
Normal 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
37
game/src/DragonLair.h
Normal 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
1151
game/src/DragonSoul.cpp
Normal file
File diff suppressed because it is too large
Load Diff
60
game/src/DragonSoul.h
Normal file
60
game/src/DragonSoul.h
Normal 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
64
game/src/FSM.cpp
Normal 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
34
game/src/FSM.h
Normal 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
|
136
game/src/FileMonitor_FreeBSD.cpp
Normal file
136
game/src/FileMonitor_FreeBSD.cpp
Normal 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 );
|
||||
}
|
47
game/src/FileMonitor_FreeBSD.h
Normal file
47
game/src/FileMonitor_FreeBSD.h
Normal 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
54
game/src/HackShield.cpp
Normal 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
24
game/src/HackShield.h
Normal 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_ */
|
||||
|
202
game/src/HackShield_Impl.cpp
Normal file
202
game/src/HackShield_Impl.cpp
Normal 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
|
||||
|
51
game/src/HackShield_Impl.h
Normal file
51
game/src/HackShield_Impl.h
Normal 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
30
game/src/IFileMonitor.h
Normal 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
135
game/src/MarkConvert.cpp
Normal 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
299
game/src/MarkImage.cpp
Normal 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
111
game/src/MarkImage.h
Normal 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
473
game/src/MarkManager.cpp
Normal 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
82
game/src/MarkManager.h
Normal 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
441
game/src/OXEvent.cpp
Normal 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
65
game/src/OXEvent.h
Normal 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
637
game/src/PetSystem.cpp
Normal 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
163
game/src/PetSystem.h
Normal 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
399
game/src/SpeedServer.cpp
Normal 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
129
game/src/SpeedServer.h
Normal 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
|
92
game/src/TrafficProfiler.cpp
Normal file
92
game/src/TrafficProfiler.cpp
Normal 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
115
game/src/TrafficProfiler.h
Normal 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
329
game/src/XTrapManager.cpp
Normal 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
67
game/src/XTrapManager.h
Normal 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
31
game/src/affect.cpp
Normal 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
183
game/src/affect.h
Normal 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
69
game/src/affect_flag.h
Normal 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
371
game/src/ani.cpp
Normal 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>0Ż<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
19
game/src/ani.h
Normal 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
67
game/src/any_function.h
Normal 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
116
game/src/any_function.inc
Normal 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
1138
game/src/arena.cpp
Normal file
File diff suppressed because it is too large
Load Diff
139
game/src/arena.h
Normal file
139
game/src/arena.h
Normal 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
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
218
game/src/auction_manager.h
Normal 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
|
5
game/src/auction_packet.h
Normal file
5
game/src/auction_packet.h
Normal 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
182
game/src/auth_brazil.cpp
Normal 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
23
game/src/auth_brazil.h
Normal 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
126
game/src/banword.cpp
Normal 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
24
game/src/banword.h
Normal 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
823
game/src/battle.cpp
Normal 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
100
game/src/battle.h
Normal 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
|
108
game/src/belt_inventory_helper.h
Normal file
108
game/src/belt_inventory_helper.h
Normal 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
249
game/src/blend_item.cpp
Normal 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
20
game/src/blend_item.h
Normal 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
151
game/src/block_country.cpp
Normal 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
18
game/src/block_country.h
Normal 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_
|
||||
|
184
game/src/buff_on_attributes.cpp
Normal file
184
game/src/buff_on_attributes.cpp
Normal 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();
|
||||
}
|
42
game/src/buff_on_attributes.h
Normal file
42
game/src/buff_on_attributes.h
Normal 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
|
38
game/src/buffer_manager.cpp
Normal file
38
game/src/buffer_manager.cpp
Normal 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
22
game/src/buffer_manager.h
Normal 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
|
70
game/src/build_locale_string.py
Normal file
70
game/src/build_locale_string.py
Normal 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
1269
game/src/building.cpp
Normal file
File diff suppressed because it is too large
Load Diff
152
game/src/building.h
Normal file
152
game/src/building.h
Normal 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
1079
game/src/castle.cpp
Normal file
File diff suppressed because it is too large
Load Diff
77
game/src/castle.h
Normal file
77
game/src/castle.h
Normal 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
7225
game/src/char.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2054
game/src/char.h
Normal file
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
837
game/src/char_affect.cpp
Normal 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
3648
game/src/char_battle.cpp
Normal file
File diff suppressed because it is too large
Load Diff
210
game/src/char_change_empire.cpp
Normal file
210
game/src/char_change_empire.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
143
game/src/char_dragonsoul.cpp
Normal file
143
game/src/char_dragonsoul.cpp
Normal 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;
|
||||
}
|
93
game/src/char_hackshield.cpp
Normal file
93
game/src/char_hackshield.cpp
Normal 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
387
game/src/char_horse.cpp
Normal 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
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
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
175
game/src/char_manager.h
Normal 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
156
game/src/char_quickslot.cpp
Normal 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
280
game/src/char_resist.cpp
Normal 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
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
1230
game/src/char_state.cpp
Normal file
File diff suppressed because it is too large
Load Diff
4
game/src/check_server.cpp
Normal file
4
game/src/check_server.cpp
Normal 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
48
game/src/check_server.h
Normal 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
402
game/src/cipher.cpp
Normal 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
60
game/src/cipher.h
Normal 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
737
game/src/cmd.cpp
Normal 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
69
game/src/cmd.h
Normal 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
267
game/src/cmd_emotion.cpp
Normal 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
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
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
34
game/src/cmd_oxevent.cpp
Normal 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
1319
game/src/config.cpp
Normal file
File diff suppressed because it is too large
Load Diff
120
game/src/config.h
Normal file
120
game/src/config.h
Normal 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
1297
game/src/constants.cpp
Normal file
File diff suppressed because it is too large
Load Diff
190
game/src/constants.h
Normal file
190
game/src/constants.h
Normal 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
136
game/src/crc32.cpp
Normal 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
Reference in New Issue
Block a user