1
0
Fork 0

convert comments to utf-8

This commit is contained in:
sdgmt2 2024-04-05 23:34:45 +02:00
parent 4a1460f36e
commit eacc808366
No known key found for this signature in database
114 changed files with 2214 additions and 2214 deletions

View File

@ -237,7 +237,7 @@ void CDragonLairManager::OnDragonDead(LPCHARACTER pDragon, DWORD KillerGuildID)
iter->second->OnDragonDead( pDragon );
// 애들 다 집으로 보내고 맵 없애기
// 애들 다 집으로 보내고 맵 없애기
tag_DragonLair_Collapse_EventInfo* info;
info = AllocEventInfo<tag_DragonLair_Collapse_EventInfo>();

View File

@ -31,7 +31,7 @@ int Gamble(std::vector<float>& vec_probs)
return -1;
}
// 가중치 테이블(prob_lst)을 받아 random_set.size()개의 index를 선택하여 random_set을 return
// 가중치 테이블(prob_lst)을 받아 random_set.size()개의 index를 선택하여 random_set을 return
bool MakeDistinctRandomNumberSet(std::list <float> prob_lst, OUT std::vector<int>& random_set)
{
int size = prob_lst.size();
@ -67,11 +67,11 @@ bool MakeDistinctRandomNumberSet(std::list <float> prob_lst, OUT std::vector<int
return true;
}
/* 용혼석 Vnum에 대한 comment
* ITEM VNUM을 10 , FEDCBA라고
* FE : . D :
* C : B :
* A : ...
/* 용혼석 Vnum에 대한 comment
* ITEM VNUM을 10 , FEDCBA라고
* FE : . D :
* C : B :
* A : ...
*/
BYTE GetType(DWORD dwVnum)
@ -169,7 +169,7 @@ bool DSManager::RefreshItemAttributes(LPITEM pDS)
return false;
}
// add_min과 add_max는 더미로 읽음.
// add_min과 add_max는 더미로 읽음.
int basic_apply_num, add_min, add_max;
if (!m_pTable->GetApplyNumSettings(ds_type, grade_idx, basic_apply_num, add_min, add_max))
{
@ -315,7 +315,7 @@ int DSManager::GetDuration(const LPITEM pItem) const
return pItem->GetDuration();
}
// 용혼석을 받아서 용심을 추출하는 함수
// 용혼석을 받아서 용심을 추출하는 함수
bool DSManager::ExtractDragonHeart(LPCHARACTER ch, LPITEM pItem, LPITEM pExtractor)
{
if (NULL == ch || NULL == pItem)
@ -397,7 +397,7 @@ bool DSManager::ExtractDragonHeart(LPCHARACTER ch, LPITEM pItem, LPITEM pExtract
}
}
// 특정 용혼석을 장비창에서 제거할 때에 성공 여부를 결정하고, 실패시 부산물을 주는 함수.
// 특정 용혼석을 장비창에서 제거할 때에 성공 여부를 결정하고, 실패시 부산물을 주는 함수.
bool DSManager::PullOut(LPCHARACTER ch, TItemPos DestCell, LPITEM& pItem, LPITEM pExtractor)
{
if (NULL == ch || NULL == pItem)
@ -406,7 +406,7 @@ bool DSManager::PullOut(LPCHARACTER ch, TItemPos DestCell, LPITEM& pItem, LPITEM
return false;
}
// 목표 위치가 valid한지 검사 후, valid하지 않다면 임의의 빈 공간을 찾는다.
// 목표 위치가 valid한지 검사 후, valid하지 않다면 임의의 빈 공간을 찾는다.
if (!IsValidCellForThisItem(pItem, DestCell))
{
int iEmptyCell = ch->GetEmptyDragonSoulInventory(pItem);
@ -430,14 +430,14 @@ bool DSManager::PullOut(LPCHARACTER ch, TItemPos DestCell, LPITEM& pItem, LPITEM
int iBonus = 0;
float fProb;
float fDice;
// 용혼석 추출 성공 여부 결정.
// 용혼석 추출 성공 여부 결정.
{
DWORD dwVnum = pItem->GetVnum();
BYTE ds_type, grade_idx, step_idx, strength_idx;
GetDragonSoulInfo(pItem->GetVnum(), ds_type, grade_idx, step_idx, strength_idx);
// 추출 정보가 없다면 일단 무조건 성공하는 것이라 생각하자.
// 추출 정보가 없다면 일단 무조건 성공하는 것이라 생각하자.
if (!m_pTable->GetDragonSoulExtValues(ds_type, grade_idx, fProb, dwByProduct))
{
pItem->AddToCharacter(ch, DestCell);
@ -454,7 +454,7 @@ bool DSManager::PullOut(LPCHARACTER ch, TItemPos DestCell, LPITEM& pItem, LPITEM
bSuccess = fDice <= (fProb * (100 + iBonus) / 100.f);
}
// 캐릭터의 용혼석 추출 및 추가 혹은 제거. 부산물 제공.
// 캐릭터의 용혼석 추출 및 추가 혹은 제거. 부산물 제공.
{
char buf[128];
@ -519,8 +519,8 @@ bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL
return false;
}
// 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
// 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
// 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
// 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
std::set <LPITEM> set_items;
for (int i = 0; i < DRAGON_SOUL_REFINE_GRID_SIZE; i++)
{
@ -529,7 +529,7 @@ bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL
LPITEM pItem = ch->GetItem(aItemPoses[i]);
if (NULL != pItem)
{
// 용혼석이 아닌 아이템이 개량창에 있을 수 없다.
// 용혼석이 아닌 아이템이 개량창에 있을 수 없다.
if (!pItem->IsDragonSoul())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB5\xEE\xB1\xDE \xB0\xB3\xB7\xAE\xBF\xA1 \xC7\xCA\xBF\xE4\xC7\xD1 \xC0\xE7\xB7\xE1\xB0\xA1 \xBE\xC6\xB4\xD5\xB4\xCF\xB4\xD9."));
@ -557,7 +557,7 @@ bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL
BYTE ds_type, grade_idx, step_idx, strength_idx;
int result_grade;
// 가장 처음 것을 강화의 기준으로 삼는다.
// 가장 처음 것을 강화의 기준으로 삼는다.
std::set <LPITEM>::iterator it = set_items.begin();
{
LPITEM pItem = *it;
@ -576,8 +576,8 @@ bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL
{
LPITEM pItem = *it;
// 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
// 별도의 알림 처리는 안함.
// 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
// 별도의 알림 처리는 안함.
if (pItem->IsEquipped())
{
return false;
@ -592,7 +592,7 @@ bool DSManager::DoRefineGrade(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL
}
}
// 클라에서 한번 갯수 체크를 하기 때문에 count != need_count라면 invalid 클라일 가능성이 크다.
// 클라에서 한번 갯수 체크를 하기 때문에 count != need_count라면 invalid 클라일 가능성이 크다.
if (count != need_count)
{
SPDLOG_ERROR("Possiblity of invalid client. Name {}", ch->GetName());
@ -679,15 +679,15 @@ bool DSManager::DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_
return false;
}
// 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
// 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
// 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
// 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
std::set <LPITEM> set_items;
for (int i = 0; i < DRAGON_SOUL_REFINE_GRID_SIZE; i++)
{
LPITEM pItem = ch->GetItem(aItemPoses[i]);
if (NULL != pItem)
{
// 용혼석이 아닌 아이템이 개량창에 있을 수 없다.
// 용혼석이 아닌 아이템이 개량창에 있을 수 없다.
if (!pItem->IsDragonSoul())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB4\xDC\xB0\xE8 \xB0\xB3\xB7\xAE\xBF\xA1 \xC7\xCA\xBF\xE4\xC7\xD1 \xC0\xE7\xB7\xE1\xB0\xA1 \xBE\xC6\xB4\xD5\xB4\xCF\xB4\xD9."));
@ -713,7 +713,7 @@ bool DSManager::DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_
BYTE ds_type, grade_idx, step_idx, strength_idx;
int result_step;
// 가장 처음 것을 강화의 기준으로 삼는다.
// 가장 처음 것을 강화의 기준으로 삼는다.
std::set <LPITEM>::iterator it = set_items.begin();
{
LPITEM pItem = *it;
@ -730,8 +730,8 @@ bool DSManager::DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_
while(++it != set_items.end())
{
LPITEM pItem = *it;
// 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
// 별도의 알림 처리는 안함.
// 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
// 별도의 알림 처리는 안함.
if (pItem->IsEquipped())
{
return false;
@ -744,7 +744,7 @@ bool DSManager::DoRefineStep(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_SOUL_
}
}
// 클라에서 한번 갯수 체크를 하기 때문에 count != need_count라면 invalid 클라일 가능성이 크다.
// 클라에서 한번 갯수 체크를 하기 때문에 count != need_count라면 invalid 클라일 가능성이 크다.
if (count != need_count)
{
SPDLOG_ERROR("Possiblity of invalid client. Name {}", ch->GetName());
@ -840,8 +840,8 @@ bool DSManager::DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_S
return false;
}
// 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
// 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
// 혹시나 모를 중복되는 item pointer 없애기 위해서 set 사용
// 이상한 패킷을 보낼 경우, 중복된 TItemPos가 있을 수도 있고, 잘못된 TItemPos가 있을 수도 있다.
std::set <LPITEM> set_items;
for (int i = 0; i < DRAGON_SOUL_REFINE_GRID_SIZE; i++)
{
@ -863,15 +863,15 @@ bool DSManager::DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_S
for (std::set <LPITEM>::iterator it = set_items.begin(); it != set_items.end(); it++)
{
LPITEM pItem = *it;
// 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
// 별도의 알림 처리는 안함.
// 클라 ui에서 장착한 아이템은 개량창에 올릴 수 없도록 막았기 때문에,
// 별도의 알림 처리는 안함.
if (pItem->IsEquipped())
{
return false;
}
// 용혼석과 강화석만이 개량창에 있을 수 있다.
// 그리고 하나씩만 있어야한다.
// 용혼석과 강화석만이 개량창에 있을 수 있다.
// 그리고 하나씩만 있어야한다.
if (pItem->IsDragonSoul())
{
if (pDragonSoul != NULL)
@ -912,14 +912,14 @@ bool DSManager::DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_S
GetDragonSoulInfo(pDragonSoul->GetVnum(), bType, bGrade, bStep, bStrength);
float fWeight = 0.f;
// 가중치 값이 없다면 강화할 수 없는 용혼석
// 가중치 값이 없다면 강화할 수 없는 용혼석
if (!m_pTable->GetWeight(bType, bGrade, bStep, bStrength + 1, fWeight))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB0\xAD\xC8\xAD\xC7\xD2 \xBC\xF6 \xBE\xF8\xB4\xC2 \xBF\xEB\xC8\xA5\xBC\xAE\xC0\xD4\xB4\xCF\xB4\xD9."));
SendRefineResultPacket(ch, DS_SUB_HEADER_REFINE_FAIL_MAX_REFINE, TItemPos(pDragonSoul->GetWindow(), pDragonSoul->GetCell()));
return false;
}
// 강화했을 때 가중치가 0이라면 더 이상 강화되서는 안된다.
// 강화했을 때 가중치가 0이라면 더 이상 강화되서는 안된다.
if (fWeight < FLT_EPSILON)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB0\xAD\xC8\xAD\xC7\xD2 \xBC\xF6 \xBE\xF8\xB4\xC2 \xBF\xEB\xC8\xA5\xBC\xAE\xC0\xD4\xB4\xCF\xB4\xD9."));
@ -988,7 +988,7 @@ bool DSManager::DoRefineStrength(LPCHARACTER ch, TItemPos (&aItemPoses)[DRAGON_S
char buf[128];
sprintf(buf, "STRENGTH : %d -> %d", bStrength, bStrength - 1);
// strength강화는 실패시 깨질 수도 있어, 원본 아이템을 바탕으로 로그를 남김.
// strength강화는 실패시 깨질 수도 있어, 원본 아이템을 바탕으로 로그를 남김.
LogManager::instance().ItemLog(ch, pDragonSoul, "DS_STRENGTH_REFINE_FAIL", buf);
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB0\xAD\xC8\xAD\xBF\xA1 \xBD\xC7\xC6\xD0\xC7\xDF\xBD\xC0\xB4\xCF\xB4\xD9."));
@ -1029,12 +1029,12 @@ int DSManager::LeftTime(LPITEM pItem) const
if (pItem == NULL)
return false;
// 일단은 timer based on wear인 용혼석만 시간 다 되어도 안 없어진다.
// 일단은 timer based on wear인 용혼석만 시간 다 되어도 안 없어진다.
if (pItem->GetProto()->cLimitTimerBasedOnWearIndex >= 0)
{
return pItem->GetSocket(ITEM_SOCKET_REMAIN_SEC);
}
// 다른 limit type인 용혼석들은 시간 되면 모두 사라지기 때문에 여기 들어온 아이템은 일단 시간이 남았다고 판단.
// 다른 limit type인 용혼석들은 시간 되면 모두 사라지기 때문에 여기 들어온 아이템은 일단 시간이 남았다고 판단.
else
{
return INT_MAX;
@ -1046,12 +1046,12 @@ bool DSManager::IsTimeLeftDragonSoul(LPITEM pItem) const
if (pItem == NULL)
return false;
// 일단은 timer based on wear인 용혼석만 시간 다 되어도 안 없어진다.
// 일단은 timer based on wear인 용혼석만 시간 다 되어도 안 없어진다.
if (pItem->GetProto()->cLimitTimerBasedOnWearIndex >= 0)
{
return pItem->GetSocket(ITEM_SOCKET_REMAIN_SEC) > 0;
}
// 다른 limit type인 용혼석들은 시간 되면 모두 사라지기 때문에 여기 들어온 아이템은 일단 시간이 남았다고 판단.
// 다른 limit type인 용혼석들은 시간 되면 모두 사라지기 때문에 여기 들어온 아이템은 일단 시간이 남았다고 판단.
else
{
return true;

View File

@ -30,14 +30,14 @@ static Pixel * LoadOldGuildMarkImageFile()
bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
{
// 폴더 생성
// 폴더 생성
#ifndef __WIN32__
mkdir("mark", S_IRWXU);
#else
_mkdir("mark");
#endif
// 인덱스 파일이 있나?
// 인덱스 파일이 있나?
#ifndef __WIN32__
if (0 != access(OLD_MARK_INDEX_FILENAME, F_OK))
#else
@ -45,13 +45,13 @@ bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
#endif
return true;
// 인덱스 파일 열기
// 인덱스 파일 열기
FILE* fp = fopen(OLD_MARK_INDEX_FILENAME, "r");
if (NULL == fp)
return false;
// 이미지 파일 열기
// 이미지 파일 열기
Pixel * oldImagePtr = LoadOldGuildMarkImageFile();
if (NULL == oldImagePtr)
@ -61,8 +61,8 @@ bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
}
/*
// guild_mark.tga가 실제 targa 파일이 아니고, 512 * 512 * 4 크기의 raw 파일이다.
// 눈으로 확인하기 위해 실제 targa 파일로 만든다.
// guild_mark.tga가 실제 targa 파일이 아니고, 512 * 512 * 4 크기의 raw 파일이다.
// 눈으로 확인하기 위해 실제 targa 파일로 만든다.
CGuildMarkImage * pkImage = new CGuildMarkImage;
pkImage->Build("guild_mark_real.tga");
pkImage->Load("guild_mark_real.tga");
@ -86,7 +86,7 @@ bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
continue;
}
// mark id -> 이미지에서의 위치 찾기
// mark id -> 이미지에서의 위치 찾기
uint row = mark_id / 32;
uint col = mark_id % 32;
@ -102,7 +102,7 @@ bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
Pixel * src = oldImagePtr + sy * 512 + sx;
Pixel * dst = mark;
// 옛날 이미지에서 마크 한개 복사
// 옛날 이미지에서 마크 한개 복사
for (int y = 0; y != SGuildMark::HEIGHT; ++y)
{
for (int x = 0; x != SGuildMark::WIDTH; ++x)
@ -111,7 +111,7 @@ bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
src += 512;
}
// 새 길드 마크 시스템에 넣는다.
// 새 길드 마크 시스템에 넣는다.
CGuildMarkManager::instance().SaveMark(guild_id, (BYTE *) mark);
line[0] = '\0';
}
@ -119,7 +119,7 @@ bool GuildMarkConvert(const std::vector<DWORD> & vecGuildID)
free(oldImagePtr);
fclose(fp);
// 컨버트는 한번만 하면되므로 파일을 옮겨준다.
// 컨버트는 한번만 하면되므로 파일을 옮겨준다.
#ifndef __WIN32__
system("mv -f guild_mark.idx guild_mark.idx.removable");
system("mv -f guild_mark.tga guild_mark.tga.removable");

View File

@ -129,10 +129,10 @@ void CGuildMarkImage::GetData(UINT x, UINT y, UINT width, UINT height, void * da
ilCopyPixels(x, y, 0, width, height, 1, IL_BGRA, IL_UNSIGNED_BYTE, data);
}
// 이미지 = 512x512
// 블럭 = 마크 4 x 4
// 마크 = 16 x 12
// 한 이미지의 블럭 = 8 x 10
// 이미지 = 512x512
// 블럭 = 마크 4 x 4
// 마크 = 16 x 12
// 한 이미지의 블럭 = 8 x 10
// SERVER
bool CGuildMarkImage::SaveMark(DWORD posMark, BYTE * pbImage)
@ -143,14 +143,14 @@ bool CGuildMarkImage::SaveMark(DWORD posMark, BYTE * pbImage)
return false;
}
// 마크를 전체 이미지에 그린다.
// 마크를 전체 이미지에 그린다.
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);
// 그려진 곳의 블럭을 업데이트
// 그려진 곳의 블럭을 업데이트
DWORD rowBlock = rowMark / SGuildMarkBlock::MARK_PER_BLOCK_HEIGHT;
DWORD colBlock = colMark / SGuildMarkBlock::MARK_PER_BLOCK_WIDTH;
@ -197,7 +197,7 @@ bool CGuildMarkImage::SaveBlockFromCompressedData(DWORD posBlock, const BYTE * p
return true;
}
void CGuildMarkImage::BuildAllBlocks() // 이미지 전체를 블럭화
void CGuildMarkImage::BuildAllBlocks() // 이미지 전체를 블럭화
{
Pixel apxBuf[SGuildMarkBlock::SIZE];
SPDLOG_INFO("GuildMarkImage::BuildAllBlocks");

View File

@ -15,7 +15,7 @@ void CGuildMarkManager::__DeleteImage(CGuildMarkImage * pkImgDel)
CGuildMarkManager::CGuildMarkManager()
{
// 남은 mark id 셋을 만든다. (서버용)
// 남은 mark id 셋을 만든다. (서버용)
for (DWORD i = 0; i < MAX_IMAGE_COUNT * CGuildMarkImage::MARK_TOTAL_COUNT; ++i)
m_setFreeMarkID.insert(i);
}
@ -44,7 +44,7 @@ void CGuildMarkManager::SetMarkPathPrefix(const char * prefix)
m_pathPrefix = prefix;
}
// 마크 인덱스 불러오기 (서버에서만 사용)
// 마크 인덱스 불러오기 (서버에서만 사용)
bool CGuildMarkManager::LoadMarkIndex()
{
char buf[64];
@ -177,7 +177,7 @@ DWORD CGuildMarkManager::__AllocMarkID(DWORD guildID)
DWORD markID = *it;
DWORD imgIdx = markID / CGuildMarkImage::MARK_TOTAL_COUNT;
CGuildMarkImage * pkImage = __GetImage(imgIdx); // 이미지가 없다면 만들기 위해
CGuildMarkImage * pkImage = __GetImage(imgIdx); // 이미지가 없다면 만들기 위해
if (pkImage && AddMarkIDByGuildID(guildID, markID))
return markID;
@ -263,7 +263,7 @@ void CGuildMarkManager::GetDiffBlocks(DWORD imgIdx, const DWORD * crcList, std::
{
mapDiffBlocks.clear();
// 클라이언트에서 서버에 없는 이미지를 요청할 수는 없다.
// 클라이언트에서 서버에 없는 이미지를 요청할 수는 없다.
if (m_mapIdx_Image.end() == m_mapIdx_Image.find(imgIdx))
{
SPDLOG_ERROR("invalid idx {}", imgIdx);
@ -290,7 +290,7 @@ bool CGuildMarkManager::SaveBlockFromCompressedData(DWORD imgIdx, DWORD posBlock
// CLIENT
bool CGuildMarkManager::GetBlockCRCList(DWORD imgIdx, DWORD * crcList)
{
// 클라이언트에서 서버에 없는 이미지를 요청할 수는 없다.
// 클라이언트에서 서버에 없는 이미지를 요청할 수는 없다.
if (m_mapIdx_Image.end() == m_mapIdx_Image.find(imgIdx))
{
SPDLOG_ERROR("invalid idx {}", imgIdx);

View File

@ -318,11 +318,11 @@ bool COXEventManager::CheckAnswer(bool answer)
int len = snprintf(chatbuf, sizeof(chatbuf),
"%s %u %u", Random::get(0, 1) == 1 ? "cheer1" : "cheer2", (DWORD)pkChar->GetVID(), 0);
// 리턴값이 sizeof(chatbuf) 이상일 경우 truncate되었다는 뜻..
// 리턴값이 sizeof(chatbuf) 이상일 경우 truncate되었다는 뜻..
if (len < 0 || len >= (int) sizeof(chatbuf))
len = sizeof(chatbuf) - 1;
// \0 문자 포함
// \0 문자 포함
++len;
TPacketGCChat pack_chat;

View File

@ -18,13 +18,13 @@ EVENTINFO(petsystem_event_info)
CPetSystem* pPetSystem;
};
// PetSystem을 update 해주는 event.
// PetSystem은 CHRACTER_MANAGER에서 기존 FSM으로 update 해주는 기존 chracters와 달리,
// Owner의 STATE를 update 할 때 _UpdateFollowAI 함수로 update 해준다.
// 그런데 owner의 state를 update를 CHRACTER_MANAGER에서 해주기 때문에,
// petsystem을 update하다가 pet을 unsummon하는 부분에서 문제가 생겼다.
// (CHRACTER_MANAGER에서 update 하면 chracter destroy가 pending되어, CPetSystem에서는 dangling 포인터를 가지고 있게 된다.)
// 따라서 PetSystem만 업데이트 해주는 event를 발생시킴.
// PetSystem을 update 해주는 event.
// PetSystem은 CHRACTER_MANAGER에서 기존 FSM으로 update 해주는 기존 chracters와 달리,
// Owner의 STATE를 update 할 때 _UpdateFollowAI 함수로 update 해준다.
// 그런데 owner의 state를 update를 CHRACTER_MANAGER에서 해주기 때문에,
// petsystem을 update하다가 pet을 unsummon하는 부분에서 문제가 생겼다.
// (CHRACTER_MANAGER에서 update 하면 chracter destroy가 pending되어, CPetSystem에서는 dangling 포인터를 가지고 있게 된다.)
// 따라서 PetSystem만 업데이트 해주는 event를 발생시킴.
EVENTFUNC(petsystem_update_event)
{
petsystem_event_info* info = dynamic_cast<petsystem_event_info*>( event->info );
@ -41,12 +41,12 @@ EVENTFUNC(petsystem_update_event)
pPetSystem->Update(0);
// 0.25초마다 갱신.
// 0.25초마다 갱신.
return PASSES_PER_SEC(1) / 4;
}
/// NOTE: 1캐릭터가 몇개의 펫을 가질 수 있는지 제한... 캐릭터마다 개수를 다르게 할거라면 변수로 넣등가... 음..
/// 가질 수 있는 개수와 동시에 소환할 수 있는 개수가 틀릴 수 있는데 이런건 기획 없으니 일단 무시
/// NOTE: 1캐릭터가 몇개의 펫을 가질 수 있는지 제한... 캐릭터마다 개수를 다르게 할거라면 변수로 넣등가... 음..
/// 가질 수 있는 개수와 동시에 소환할 수 있는 개수가 틀릴 수 있는데 이런건 기획 없으니 일단 무시
const float PET_COUNT_LIMIT = 3;
///////////////////////////////////////////////////////////////////////////////////////
@ -119,7 +119,7 @@ void CPetActor::Unsummon()
{
if (true == this->IsSummoned())
{
// 버프 삭제
// 버프 삭제
this->ClearBuff();
this->SetSummonItem(NULL);
if (NULL != m_pkOwner)
@ -175,14 +175,14 @@ DWORD CPetActor::Summon(const char* petName, LPITEM pSummonItem, bool bSpawnFar)
// m_pkOwner->DetailLog();
// m_pkChar->DetailLog();
//펫의 국가를 주인의 국가로 설정함.
//펫의 국가를 주인의 국가로 설정함.
m_pkChar->SetEmpire(m_pkOwner->GetEmpire());
m_dwVID = m_pkChar->GetVID();
this->SetName(petName);
// SetSummonItem(pSummonItem)를 부른 후에 ComputePoints를 부르면 버프 적용됨.
// SetSummonItem(pSummonItem)를 부른 후에 ComputePoints를 부르면 버프 적용됨.
this->SetSummonItem(pSummonItem);
m_pkOwner->ComputePoints();
m_pkChar->Show(m_pkOwner->GetMapIndex(), x, y, z);
@ -197,11 +197,11 @@ bool CPetActor::_UpdatAloneActionAI(float fMinDist, float fMaxDist)
float dest_x = GetOwner()->GetX() + fDist * cos(r);
float dest_y = GetOwner()->GetY() + fDist * sin(r);
//m_pkChar->SetRotation(Random::get(0, 359)); // 방향은 랜덤으로 설정
//m_pkChar->SetRotation(Random::get(0, 359)); // 방향은 랜덤으로 설정
//GetDeltaByDegree(m_pkChar->GetRotation(), fDist, &fx, &fy);
// 느슨한 못감 속성 체크; 최종 위치와 중간 위치가 갈수없다면 가지 않는다.
// 느슨한 못감 속성 체크; 최종 위치와 중간 위치가 갈수없다면 가지 않는다.
//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;
@ -218,7 +218,7 @@ bool CPetActor::_UpdatAloneActionAI(float fMinDist, float fMaxDist)
return true;
}
// char_state.cpp StateHorse함수 그냥 C&P -_-;
// char_state.cpp StateHorse함수 그냥 C&P -_-;
bool CPetActor::_UpdateFollowAI()
{
if (0 == m_pkChar->m_pkMobData)
@ -227,9 +227,9 @@ bool CPetActor::_UpdateFollowAI()
return false;
}
// NOTE: 캐릭터(펫)의 원래 이동 속도를 알아야 하는데, 해당 값(m_pkChar->m_pkMobData->m_table.sMovingSpeed)을 직접적으로 접근해서 알아낼 수도 있지만
// m_pkChar->m_pkMobData 값이 invalid한 경우가 자주 발생함. 현재 시간관계상 원인은 다음에 파악하고 일단은 m_pkChar->m_pkMobData 값을 아예 사용하지 않도록 함.
// 여기서 매번 검사하는 이유는 최초 초기화 할 때 정상 값을 제대로 못얻어오는 경우도 있음.. -_-;; ㅠㅠㅠㅠㅠㅠㅠㅠㅠ
// NOTE: 캐릭터(펫)의 원래 이동 속도를 알아야 하는데, 해당 값(m_pkChar->m_pkMobData->m_table.sMovingSpeed)을 직접적으로 접근해서 알아낼 수도 있지만
// m_pkChar->m_pkMobData 값이 invalid한 경우가 자주 발생함. 현재 시간관계상 원인은 다음에 파악하고 일단은 m_pkChar->m_pkMobData 값을 아예 사용하지 않도록 함.
// 여기서 매번 검사하는 이유는 최초 초기화 할 때 정상 값을 제대로 못얻어오는 경우도 있음.. -_-;; ㅠㅠㅠㅠㅠㅠㅠㅠㅠ
if (0 == m_originalMoveSpeed)
{
const CMob* mobData = CMobManager::Instance().Get(m_dwVnum);
@ -237,14 +237,14 @@ bool CPetActor::_UpdateFollowAI()
if (0 != mobData)
m_originalMoveSpeed = mobData->m_table.sMovingSpeed;
}
float START_FOLLOW_DISTANCE = 300.0f; // 이 거리 이상 떨어지면 쫓아가기 시작함
float START_RUN_DISTANCE = 900.0f; // 이 거리 이상 떨어지면 뛰어서 쫓아감.
float START_FOLLOW_DISTANCE = 300.0f; // 이 거리 이상 떨어지면 쫓아가기 시작함
float START_RUN_DISTANCE = 900.0f; // 이 거리 이상 떨어지면 뛰어서 쫓아감.
float RESPAWN_DISTANCE = 4500.f; // 이 거리 이상 멀어지면 주인 옆으로 소환함.
int APPROACH = 200; // 접근 거리
float RESPAWN_DISTANCE = 4500.f; // 이 거리 이상 멀어지면 주인 옆으로 소환함.
int APPROACH = 200; // 접근 거리
bool bDoMoveAlone = true; // 캐릭터와 가까이 있을 때 혼자 여기저기 움직일건지 여부 -_-;
bool bRun = false; // 뛰어야 하나?
bool bDoMoveAlone = true; // 캐릭터와 가까이 있을 때 혼자 여기저기 움직일건지 여부 -_-;
bool bRun = false; // 뛰어야 하나?
DWORD currentTime = get_dword_time();
@ -272,7 +272,7 @@ bool CPetActor::_UpdateFollowAI()
bRun = true;
}
m_pkChar->SetNowWalking(!bRun); // NOTE: 함수 이름보고 멈추는건줄 알았는데 SetNowWalking(false) 하면 뛰는거임.. -_-;
m_pkChar->SetNowWalking(!bRun); // NOTE: 함수 이름보고 멈추는건줄 알았는데 SetNowWalking(false) 하면 뛰는거임.. -_-;
Follow(APPROACH);
@ -288,7 +288,7 @@ bool CPetActor::_UpdateFollowAI()
// m_dwLastActionTime = currentTime;
// }
//}
// Follow 중이지만 주인과 일정 거리 이내로 가까워졌다면 멈춤
// Follow 중이지만 주인과 일정 거리 이내로 가까워졌다면 멈춤
else
m_pkChar->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
//else if (currentTime - m_dwLastActionTime > Random::get(5000, 12000))
@ -303,8 +303,8 @@ bool CPetActor::Update(DWORD deltaTime)
{
bool bResult = true;
// 펫 주인이 죽었거나, 소환된 펫의 상태가 이상하다면 펫을 없앰. (NOTE: 가끔가다 이런 저런 이유로 소환된 펫이 DEAD 상태에 빠지는 경우가 있음-_-;)
// 펫을 소환한 아이템이 없거나, 내가 가진 상태가 아니라면 펫을 없앰.
// 펫 주인이 죽었거나, 소환된 펫의 상태가 이상하다면 펫을 없앰. (NOTE: 가끔가다 이런 저런 이유로 소환된 펫이 DEAD 상태에 빠지는 경우가 있음-_-;)
// 펫을 소환한 아이템이 없거나, 내가 가진 상태가 아니라면 펫을 없앰.
if (m_pkOwner->IsDead() || (IsSummoned() && m_pkChar->IsDead())
|| NULL == ITEM_MANAGER::instance().FindByVID(this->GetSummonItemVID())
|| ITEM_MANAGER::instance().FindByVID(this->GetSummonItemVID())->GetOwner() != this->GetOwner()
@ -320,10 +320,10 @@ bool CPetActor::Update(DWORD deltaTime)
return bResult;
}
//NOTE : 주의!!! MinDistance를 크게 잡으면 그 변위만큼의 변화동안은 follow하지 않는다,
//NOTE : 주의!!! MinDistance를 크게 잡으면 그 변위만큼의 변화동안은 follow하지 않는다,
bool CPetActor::Follow(float fMinDistance)
{
// 가려는 위치를 바라봐야 한다.
// 가려는 위치를 바라봐야 한다.
if( !m_pkOwner || !m_pkChar)
return false;
@ -367,7 +367,7 @@ void CPetActor::SetSummonItem (LPITEM pItem)
void CPetActor::GiveBuff()
{
// 파황 펫 버프는 던전에서만 발생함.
// 파황 펫 버프는 던전에서만 발생함.
if (34004 == m_dwVnum || 34009 == m_dwVnum)
{
if (NULL == m_pkOwner->GetDungeon())
@ -432,15 +432,15 @@ void CPetSystem::Destroy()
m_petActorMap.clear();
}
/// 펫 시스템 업데이트. 등록된 펫들의 AI 처리 등을 함.
/// 펫 시스템 업데이트. 등록된 펫들의 AI 처리 등을 함.
bool CPetSystem::Update(DWORD deltaTime)
{
bool bResult = true;
DWORD currentTime = get_dword_time();
// CHARACTER_MANAGER에서 캐릭터류 Update할 때 매개변수로 주는 (Pulse라고 되어있는)값이 이전 프레임과의 시간차이인줄 알았는데
// 전혀 다른 값이라서-_-; 여기에 입력으로 들어오는 deltaTime은 의미가 없음ㅠㅠ
// CHARACTER_MANAGER에서 캐릭터류 Update할 때 매개변수로 주는 (Pulse라고 되어있는)값이 이전 프레임과의 시간차이인줄 알았는데
// 전혀 다른 값이라서-_-; 여기에 입력으로 들어오는 deltaTime은 의미가 없음ㅠㅠ
if (m_dwUpdatePeriod > currentTime - m_dwLastUpdateTime)
return true;
@ -473,7 +473,7 @@ bool CPetSystem::Update(DWORD deltaTime)
return bResult;
}
/// 관리 목록에서 펫을 지움
/// 관리 목록에서 펫을 지움
void CPetSystem::DeletePet(DWORD mobVnum)
{
TPetActorMap::iterator iter = m_petActorMap.find(mobVnum);
@ -494,7 +494,7 @@ void CPetSystem::DeletePet(DWORD mobVnum)
m_petActorMap.erase(iter);
}
/// 관리 목록에서 펫을 지움
/// 관리 목록에서 펫을 지움
void CPetSystem::DeletePet(CPetActor* petActor)
{
for (TPetActorMap::iterator iter = m_petActorMap.begin(); iter != m_petActorMap.end(); ++iter)
@ -542,7 +542,7 @@ CPetActor* CPetSystem::Summon(DWORD mobVnum, LPITEM pSummonItem, const char* pet
{
CPetActor* petActor = this->GetByVnum(mobVnum);
// 등록된 펫이 아니라면 새로 생성 후 관리 목록에 등록함.
// 등록된 펫이 아니라면 새로 생성 후 관리 목록에 등록함.
if (0 == petActor)
{
petActor = M2_NEW CPetActor(m_pkOwner, mobVnum, options);
@ -557,7 +557,7 @@ CPetActor* CPetSystem::Summon(DWORD mobVnum, LPITEM pSummonItem, const char* pet
info->pPetSystem = this;
m_pkPetSystemUpdateEvent = event_create(petsystem_update_event, info, PASSES_PER_SEC(1) / 4); // 0.25초
m_pkPetSystemUpdateEvent = event_create(petsystem_update_event, info, PASSES_PER_SEC(1) / 4); // 0.25초
}
return petActor;
@ -589,7 +589,7 @@ CPetActor* CPetSystem::GetByVID(DWORD vid) const
return bFound ? petActor : 0;
}
/// 등록 된 펫 중에서 주어진 몹 VNUM을 가진 액터를 반환하는 함수.
/// 등록 된 펫 중에서 주어진 몹 VNUM을 가진 액터를 반환하는 함수.
CPetActor* CPetSystem::GetByVnum(DWORD vnum) const
{
CPetActor* petActor = 0;

View File

@ -3,7 +3,7 @@
#include "SpeedServer.h"
#include "locale_service.h"
// 쾌도 서버 보너스 경험치 시스템
// 쾌도 서버 보너스 경험치 시스템
// by rtsummit
CSpeedServerManager::CSpeedServerManager()
@ -361,13 +361,13 @@ HME CSpeedServerEmpireExp::GetCurrentExpPriv(int &duration, bool &is_change)
HME hme;
// 현재 날짜가 holiday이면 holiday bonus를 도입한다.
// 현재 날짜가 holiday이면 holiday bonus를 도입한다.
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++)
{
// 현재 시각이 시간 구간 안에 포함되면,
// 현재 시각이 시간 구간 안에 포함되면,
if (total_sec < (it->hour * 3600 + it->min * 60 ))
{
hme = *it;
@ -380,7 +380,7 @@ HME CSpeedServerEmpireExp::GetCurrentExpPriv(int &duration, bool &is_change)
for (std::list <HME>::iterator it = wday_exp_table[datetime->tm_wday].begin();
it != wday_exp_table[datetime->tm_wday].end(); it++)
{
// 현재 시각이 시간 구간 안에 포함되면,
// 현재 시각이 시간 구간 안에 포함되면,
if (total_sec < (it->hour * 3600 + it->min * 60 ))
{
hme = *it;

View File

@ -55,7 +55,7 @@ const char* FN_weapon_type(int weapon)
class ANI
{
protected:
// [종족][일반0탈것1][무기][콤보]
// [종족][일반0탈것1][무기][콤보]
DWORD m_speed[MAIN_RACE_MAX_NUM][2][WEAPON_NUM_TYPES][9];
public:
@ -126,14 +126,14 @@ ANI::ANI()
bool ANI::load()
{
const char* dir_name[MAIN_RACE_MAX_NUM] = {
"data/pc/warrior", // 무사(남)
"data/pc/assassin", // 자객(여)
"data/pc/sura", // 수라(남)
"data/pc/shaman", // 무당(여)
"data/pc2/warrior", // 무사(여)
"data/pc2/assassin", // 자객(남)
"data/pc2/sura", // 수라(여)
"data/pc2/shaman" // 무당(남)
"data/pc/warrior", // 무사(남)
"data/pc/assassin", // 자객(여)
"data/pc/sura", // 수라(남)
"data/pc/shaman", // 무당(여)
"data/pc2/warrior", // 무사(여)
"data/pc2/assassin", // 자객(남)
"data/pc2/sura", // 수라(여)
"data/pc2/shaman" // 무당(남)
};
for (int race = 0; race <MAIN_RACE_MAX_NUM; ++race)
@ -203,13 +203,13 @@ bool ANI::load_one_race(int race, const char *dir_name)
for (BYTE combo = 1; combo <= 8; ++combo)
{
// 말 안탔을 때
// 말 안탔을 때
m_speed[race][0][weapon][combo] = load_one_weapon(dir_name, weapon, combo, false);
m_speed[race][0][weapon][0] = std::min(m_speed[race][0][weapon][0], m_speed[race][0][weapon][combo]); // 최소값
m_speed[race][0][weapon][0] = std::min(m_speed[race][0][weapon][0], m_speed[race][0][weapon][combo]); // 최소값
// 말 탔을 때
// 말 탔을 때
m_speed[race][1][weapon][combo] = load_one_weapon(dir_name, weapon, combo, true);
m_speed[race][1][weapon][0] = std::min(m_speed[race][1][weapon][0], m_speed[race][1][weapon][combo]); // 최소값
m_speed[race][1][weapon][0] = std::min(m_speed[race][1][weapon][0], m_speed[race][1][weapon][combo]); // 최소값
SPDLOG_TRACE("combo{:02} speed={} horse={}",
combo, m_speed[race][0][weapon][combo], m_speed[race][1][weapon][combo]);
@ -337,8 +337,8 @@ DWORD ani_attack_speed(LPCHARACTER ch)
ch->GetPoint(POINT_ATT_SPEED));
*/
/* 투핸디드 소드의 경우 삼연참공격과 승마시 */
/* 오류가 많아 한손검 속도로 생각하자 */
/* 투핸디드 소드의 경우 삼연참공격과 승마시 */
/* 오류가 많아 한손검 속도로 생각하자 */
if (weapon == WEAPON_TWO_HANDED)
weapon = WEAPON_SWORD;

View File

@ -290,7 +290,7 @@ EVENTFUNC(ready_to_start_event)
duelStart.header = HEADER_GC_DUEL_START;
duelStart.wSize = sizeof(TPacketGCDuelStart) + 4;
DWORD dwOppList[8]; // 최대 파티원 8명 이므로..
DWORD dwOppList[8]; // 최대 파티원 8명 이므로..
dwOppList[0] = (DWORD)chB->GetVID();
TEMP_BUFFER buf;
@ -339,7 +339,7 @@ EVENTFUNC(ready_to_start_event)
TEMP_BUFFER buf;
TEMP_BUFFER buf2;
DWORD dwOppList[8]; // 최대 파티원 8명 이므로..
DWORD dwOppList[8]; // 최대 파티원 8명 이므로..
TPacketGCDuelStart duelStart;
duelStart.header = HEADER_GC_DUEL_START;
duelStart.wSize = sizeof(TPacketGCDuelStart) + 4;
@ -678,7 +678,7 @@ bool CArenaMap::CanAttack(LPCHARACTER pCharAttacker, LPCHARACTER pCharVictim)
bool CArena::CanAttack(DWORD dwPIDA, DWORD dwPIDB)
{
// 1:1 전용 다대다 할 경우 수정 필요
// 1:1 전용 다대다 할 경우 수정 필요
if (m_dwPIDA == dwPIDA && m_dwPIDB == dwPIDB) return true;
if (m_dwPIDA == dwPIDB && m_dwPIDB == dwPIDA) return true;
@ -728,7 +728,7 @@ bool CArena::OnDead(DWORD dwPIDA, DWORD dwPIDB)
if (pCharA == NULL && pCharB == NULL)
{
// 둘다 접속이 끊어졌다 ?!
// 둘다 접속이 끊어졌다 ?!
SendChatPacketToObserver(CHAT_TYPE_NOTICE, LC_TEXT("\xB4\xEB\xB7\xC3\xC0\xDA \xB9\xAE\xC1\xA6\xB7\xCE \xC0\xCE\xC7\xCF\xBF\xA9 \xB4\xEB\xB7\xC3\xC0\xBB \xC1\xDF\xB4\xDC\xC7\xD5\xB4\xCF\xB4\xD9."));
restart = false;
}
@ -811,7 +811,7 @@ bool CArena::OnDead(DWORD dwPIDA, DWORD dwPIDB)
}
else
{
// 오면 안된다 ?!
// 오면 안된다 ?!
}
if (restart == false)

View File

@ -215,7 +215,7 @@ void AuctionBoard::YourItemInfoList (TItemInfoVec& vec, DWORD player_id, int sta
}
// 0~1, 2~3, 4~5, 6~7, 8~9
// 짝수면 descending, 홀수면 accending.
// 짝수면 descending, 홀수면 accending.
struct FCheckGradeSatisfied
{
BYTE grade;
@ -796,7 +796,7 @@ void AuctionManager::YourBidItemInfoList (AuctionBoard::TItemInfoVec& vec, DWORD
}
else
{
// expired 만들고 여기서 넣어야한다.
// expired 만들고 여기서 넣어야한다.
}
}
}
@ -975,7 +975,7 @@ void AuctionManager::bid (LPCHARACTER ch, DWORD item_id, int bid_price)
}
// fixme
// 반드시 돈!!!
// 반드시 돈!!!
void AuctionManager::immediate_purchase (LPCHARACTER ch, DWORD item_id)
{
TAuctionItemInfo* item_info = GetAuctionItemInfo (item_id);
@ -1005,7 +1005,7 @@ void AuctionManager::immediate_purchase (LPCHARACTER ch, DWORD item_id)
db_clientdesc->DBPacket(HEADER_GD_COMMAND_AUCTION, ch->GetPlayerID(), &pack_impur, sizeof(TPacketGDCommnadAuction));
}
// 시작
// 시작
void AuctionManager::get_auctioned_item (LPCHARACTER ch, DWORD item_id, DWORD item_num)
{
TItemTable* proto = ITEM_MANAGER::instance().GetTable(item_num);
@ -1120,7 +1120,7 @@ void AuctionManager::bid_cancel (LPCHARACTER ch, DWORD item_id)
db_clientdesc->DBPacket(HEADER_GD_COMMAND_AUCTION, ch->GetPlayerID(), &pack_bc, sizeof(TPacketGDCommnadAuction));
}
// 끝
// 끝
void AuctionManager::recv_result_auction (DWORD commander_id, TPacketDGResultAuction* cmd_result)
{
LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(commander_id);
@ -1354,7 +1354,7 @@ void AuctionManager::recv_result_auction (DWORD commander_id, TPacketDGResultAuc
}
else
{
// insert하면 lock이 풀린다.
// insert하면 lock이 풀린다.
DWORD item_id = cmd_result->target;
cmd_result++;
TAuctionItemInfo* auction_info = (TAuctionItemInfo*)cmd_result;

View File

@ -3,7 +3,7 @@
#include "banword.h"
#include "config.h"
extern void SendLog(const char * c_pszBuf); // 운영자에게만 공지
extern void SendLog(const char * c_pszBuf); // 운영자에게만 공지
CBanwordManager::CBanwordManager()
{

View File

@ -46,7 +46,7 @@ bool timed_event_cancel(LPCHARACTER ch)
}
/* RECALL_DELAY
if (ch->m_pk_RecallEvent)
{
event_cancel(&ch->m_pkRecallEvent);
@ -59,11 +59,11 @@ bool timed_event_cancel(LPCHARACTER ch)
bool battle_is_attackable(LPCHARACTER ch, LPCHARACTER victim)
{
// 상대방이 죽었으면 중단한다.
// 상대방이 죽었으면 중단한다.
if (victim->IsDead())
return false;
// 안전지대면 중단
// 안전지대면 중단
{
SECTREE *sectree = NULL;
@ -77,7 +77,7 @@ bool battle_is_attackable(LPCHARACTER ch, LPCHARACTER victim)
}
// 내가 죽었으면 중단한다.
// 내가 죽었으면 중단한다.
if (ch->IsStun() || ch->IsDead())
return false;
@ -119,7 +119,7 @@ int battle_melee_attack(LPCHARACTER ch, LPCHARACTER victim)
if (test_server&&ch->IsPC())
SPDLOG_TRACE("battle_melee_attack : [{}] attack to [{}]", ch->GetName(), victim->GetName());
// 거리 체크
// 거리 체크
int distance = DISTANCE_APPROX(ch->GetX() - victim->GetX(), ch->GetY() - victim->GetY());
if (!victim->IsBuilding())
@ -128,12 +128,12 @@ int battle_melee_attack(LPCHARACTER ch, LPCHARACTER victim)
if (false == ch->IsPC())
{
// 몬스터의 경우 몬스터 공격 거리를 사용
// 몬스터의 경우 몬스터 공격 거리를 사용
max = (int) (ch->GetMobAttackRange() * 1.15f);
}
else
{
// PC일 경우 상대가 melee 몹일 경우 몹의 공격 거리가 최대 공격 거리
// PC일 경우 상대가 melee 몹일 경우 몹의 공격 거리가 최대 공격 거리
if (false == victim->IsPC() && BATTLE_TYPE_MELEE == victim->GetMobBattleType())
max = std::max(300, (int) (victim->GetMobAttackRange() * 1.15f));
}
@ -161,7 +161,7 @@ int battle_melee_attack(LPCHARACTER ch, LPCHARACTER victim)
return battle_hit(ch, victim);
}
// 실제 GET_BATTLE_VICTIM을 NULL로 만들고 이벤트를 캔슬 시킨다.
// 실제 GET_BATTLE_VICTIM을 NULL로 만들고 이벤트를 캔슬 시킨다.
void battle_end_ex(LPCHARACTER ch)
{
if (ch->IsPosition(POS_FIGHTING))
@ -208,7 +208,7 @@ float CalcAttackRating(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, bool bIgnor
int iARSrc;
int iERSrc;
if (LC_IsYMIR()) // 천마
if (LC_IsYMIR()) // 천마
{
iARSrc = std::min(90, pkAttacker->GetPolymorphPoint(POINT_DX));
iERSrc = std::min(90, pkVictim->GetPolymorphPoint(POINT_DX));
@ -238,11 +238,11 @@ float CalcAttackRating(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, bool bIgnor
int CalcAttBonus(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, int iAtk)
{
// PvP에는 적용하지않음
// PvP에는 적용하지않음
if (!pkVictim->IsPC())
iAtk += pkAttacker->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_ATTACK_BONUS);
// PvP에는 적용하지않음
// PvP에는 적용하지않음
if (!pkAttacker->IsPC())
{
int iReduceDamagePct = pkVictim->GetMarriageBonus(UNIQUE_ITEM_MARRIAGE_TRANSFER_DAMAGE);
@ -327,9 +327,9 @@ int CalcAttBonus(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, int iAtk)
}
}
//[ mob -> PC ] 원소 속성 방어 적용
//[ mob -> PC ] 원소 속성 방어 적용
//2013/01/17
//몬스터 속성공격 데미지의 30%에 해당하는 수치에만 저항이 적용됨.
//몬스터 속성공격 데미지의 30%에 해당하는 수치에만 저항이 적용됨.
if (pkAttacker->IsNPC() && pkVictim->IsPC())
{
if (pkAttacker->IsRaceFlag(RACE_FLAG_ATT_ELEC))
@ -553,7 +553,7 @@ int CalcArrowDamage(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, LPITEM pkBow,
if (!pkArrow)
return 0;
// 타격치 계산부
// 타격치 계산부
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);
@ -613,7 +613,7 @@ int CalcArrowDamage(LPCHARACTER pkAttacker, LPCHARACTER pkVictim, LPITEM pkBow,
void NormalAttackAffect(LPCHARACTER pkAttacker, LPCHARACTER pkVictim)
{
// 독 공격은 특이하므로 특수 처리
// 독 공격은 특이하므로 특수 처리
if (pkAttacker->GetPoint(POINT_POISON_PCT) && !pkVictim->IsAffectFlag(AFF_POISON))
{
if (Random::get(1, 100) <= pkAttacker->GetPoint(POINT_POISON_PCT))
@ -637,7 +637,7 @@ int battle_hit(LPCHARACTER pkAttacker, LPCHARACTER pkVictim)
NormalAttackAffect(pkAttacker, pkVictim);
// 데미지 계산
// 데미지 계산
//iDam = iDam * (100 - pkVictim->GetPoint(POINT_RESIST)) / 100;
LPITEM pkWeapon = pkAttacker->GetWear(WEAR_WEAPON);
@ -670,7 +670,7 @@ int battle_hit(LPCHARACTER pkAttacker, LPCHARACTER pkVictim)
}
//최종적인 데미지 보정. (2011년 2월 현재 대왕거미에게만 적용.)
//최종적인 데미지 보정. (2011년 2월 현재 대왕거미에게만 적용.)
float attMul = pkAttacker->GetAttMul();
float tempIDam = iDam;
iDam = attMul * tempIDam + 0.5f;
@ -691,19 +691,19 @@ DWORD GET_ATTACK_SPEED(LPCHARACTER ch)
return 1000;
LPITEM item = ch->GetWear(WEAR_WEAPON);
DWORD default_bonus = SPEEDHACK_LIMIT_BONUS * 3; // 유두리 공속(기본 80) (일반 유저가 speed hack 에 걸리는 것을 막기 위해 *3 추가. 2013.09.11 CYH)
DWORD default_bonus = SPEEDHACK_LIMIT_BONUS * 3; // 유두리 공속(기본 80) (일반 유저가 speed hack 에 걸리는 것을 막기 위해 *3 추가. 2013.09.11 CYH)
DWORD riding_bonus = 0;
if (ch->IsRiding())
{
// 뭔가를 탔으면 추가공속 50
// 뭔가를 탔으면 추가공속 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);
// 단검의 경우 공속 2배
// 단검의 경우 공속 2배
if (item && item->GetSubType() == WEAPON_DAGGER)
real_speed /= 2;

View File

@ -170,10 +170,10 @@ static int FN_random_index()
return 0;
}
// 충기환의 확률 테이블
// blend.txt에서 확률도 받도록 고치면 깔끔하겠지만
// 각 나라별로 item proto 등을 따로 관리하므로,
// 혼란이 올 수 있어 이렇게 추가한다.
// 충기환의 확률 테이블
// blend.txt에서 확률도 받도록 고치면 깔끔하겠지만
// 각 나라별로 item proto 등을 따로 관리하므로,
// 혼란이 올 수 있어 이렇게 추가한다.
// by rtsummit
static int FN_ECS_random_index()

View File

@ -119,7 +119,7 @@ bool is_blocked_country_ip(const char *user_ip)
#endif
{
SPDLOG_INFO("BLOCKED_COUNTRY_IP ({}) : YES", user_ip);
return true; // 아이피가 괴상하니 일단 블럭처리
return true; // 아이피가 괴상하니 일단 블럭처리
}
ip_number = htonl(st_addr.s_addr);

View File

@ -39,8 +39,8 @@ void CBuffOnAttributes::RemoveBuffFromItem(LPITEM pItem)
{
TPlayerItemAttribute attr = pItem->GetAttribute(j);
TMapAttr::iterator it = m_map_additional_attrs.find(attr.bType);
// m_map_additional_attrs에서 해당 attribute type에 대한 값을 제거하고,
// 변경된 값의 (m_bBuffValue)%만큼의 버프 효과 감소
// m_map_additional_attrs에서 해당 attribute type에 대한 값을 제거하고,
// 변경된 값의 (m_bBuffValue)%만큼의 버프 효과 감소
if (it != m_map_additional_attrs.end())
{
int& sum_of_attr_value = it->second;
@ -76,15 +76,15 @@ void CBuffOnAttributes::AddBuffFromItem(LPITEM pItem)
TPlayerItemAttribute attr = pItem->GetAttribute(j);
TMapAttr::iterator it = m_map_additional_attrs.find(attr.bType);
// m_map_additional_attrs에서 해당 attribute type에 대한 값이 없다면 추가.
// 추가된 값의 (m_bBuffValue)%만큼의 버프 효과 추가
// m_map_additional_attrs에서 해당 attribute type에 대한 값이 없다면 추가.
// 추가된 값의 (m_bBuffValue)%만큼의 버프 효과 추가
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에서 해당 attribute type에 대한 값이 있다면, 그 값을 증가시키고,
// 변경된 값의 (m_bBuffValue)%만큼의 버프 효과 추가
// m_map_additional_attrs에서 해당 attribute type에 대한 값이 있다면, 그 값을 증가시키고,
// 변경된 값의 (m_bBuffValue)%만큼의 버프 효과 추가
else
{
int& sum_of_attr_value = it->second;
@ -105,8 +105,8 @@ void CBuffOnAttributes::ChangeBuffValue(BYTE bNewValue)
Off();
else
{
// 기존에, m_map_additional_attrs의 값의 (m_bBuffValue)%만큼이 버프로 들어가 있었으므로,
// (bNewValue)%만큼으로 값을 변경함.
// 기존에, m_map_additional_attrs의 값의 (m_bBuffValue)%만큼이 버프로 들어가 있었으므로,
// (bNewValue)%만큼으로 값을 변경함.
for (TMapAttr::iterator it = m_map_additional_attrs.begin(); it != m_map_additional_attrs.end(); it++)
{
int& sum_of_attr_value = it->second;

View File

@ -112,7 +112,7 @@ void CObject::EncodeInsertPacket(LPENTITY entity)
pack.z = GetZ();
pack.wRaceNum = m_data.dwVnum;
// 빌딩 회전 정보(벽일때는 문 위치)를 변환
// 빌딩 회전 정보(벽일때는 문 위치)를 변환
pack.dwAffectFlag[0] = unsigned(m_data.xRot);
pack.dwAffectFlag[1] = unsigned(m_data.yRot);
@ -298,7 +298,7 @@ void CObject::RegenNPC()
m_chNPC->SetGuild(pGuild);
// 힘의 신전일 경우 길드 레벨을 길마에게 저장해놓는다
// 힘의 신전일 경우 길드 레벨을 길마에게 저장해놓는다
if ( m_pProto->dwVnum == 14061 || m_pProto->dwVnum == 14062 || m_pProto->dwVnum == 14063 )
{
quest::PC* pPC = quest::CQuestManager::instance().GetPC(pGuild->GetMasterPID());
@ -690,10 +690,10 @@ TObjectProto * CManager::GetObjectProto(DWORD dwVnum)
bool CManager::LoadLand(TLand * pTable) // from DB
{
// MapAllow에 없는 맵의 땅일지라도 load를 해야한다.
// 건물(object)이 어느 길드에 속해 있는지 알기 위해서는 건물이 세위진 땅이 어느 길드 소속인지 알아한다.
// 만약 땅을 load해 놓지 않으면 길드 건물이 어느 길드에 소속된 건지 알지 못해서
// 길드 건물에 의한 길드 버프를 받지 못한다.
// MapAllow에 없는 맵의 땅일지라도 load를 해야한다.
// 건물(object)이 어느 길드에 속해 있는지 알기 위해서는 건물이 세위진 땅이 어느 길드 소속인지 알아한다.
// 만약 땅을 load해 놓지 않으면 길드 건물이 어느 길드에 소속된 건지 알지 못해서
// 길드 건물에 의한 길드 버프를 받지 못한다.
//if (!map_allow_find(pTable->lMapIndex))
// return false;
@ -1098,7 +1098,7 @@ bool CLand::RequestCreateWall(int nMapIndex, float rot)
int wall_half_w = 1000;
int wall_half_h = 1362;
if (rot == 0.0f) // 남쪽 문
if (rot == 0.0f) // 남쪽 문
{
int door_x = wall_x;
int door_y = wall_y + wall_half_h;
@ -1107,7 +1107,7 @@ bool CLand::RequestCreateWall(int nMapIndex, float rot)
RequestCreateObject(WALL_LEFT_VNUM, nMapIndex, wall_x - wall_half_w, wall_y, door_x, door_y, 0.0f, WALL_ANOTHER_CHECKING_ENABLE);
RequestCreateObject(WALL_RIGHT_VNUM, nMapIndex, wall_x + wall_half_w, wall_y, door_x, door_y, 0.0f, WALL_ANOTHER_CHECKING_ENABLE);
}
else if (rot == 180.0f) // 북쪽 문
else if (rot == 180.0f) // 북쪽 문
{
int door_x = wall_x;
int door_y = wall_y - wall_half_h;
@ -1116,7 +1116,7 @@ bool CLand::RequestCreateWall(int nMapIndex, float rot)
RequestCreateObject(WALL_LEFT_VNUM, nMapIndex, wall_x - wall_half_w, wall_y, door_x, door_y, 0.0f, WALL_ANOTHER_CHECKING_ENABLE);
RequestCreateObject(WALL_RIGHT_VNUM, nMapIndex, wall_x + wall_half_w, wall_y, door_x, door_y, 0.0f, WALL_ANOTHER_CHECKING_ENABLE);
}
else if (rot == 90.0f) // 동쪽 문
else if (rot == 90.0f) // 동쪽 문
{
int door_x = wall_x + wall_half_h;
int door_y = wall_y;
@ -1125,7 +1125,7 @@ bool CLand::RequestCreateWall(int nMapIndex, float rot)
RequestCreateObject(WALL_LEFT_VNUM, nMapIndex, wall_x, wall_y - wall_half_w, door_x, door_y, 90.0f, WALL_ANOTHER_CHECKING_ENABLE);
RequestCreateObject(WALL_RIGHT_VNUM, nMapIndex, wall_x, wall_y + wall_half_w, door_x, door_y, 90.0f, WALL_ANOTHER_CHECKING_ENABLE);
}
else if (rot == 270.0f) // 서쪽 문
else if (rot == 270.0f) // 서쪽 문
{
int door_x = wall_x - wall_half_h;
int door_y = wall_y;

View File

@ -3,8 +3,8 @@
* file : castle.cpp
* author : mhh
* description :
* : 11506 - 11510
* : 8012 - 8014, 8024-8027
* : 11506 - 11510
* : 8012 - 8014, 8024-8027
*/
#define _castle_cpp_
@ -21,13 +21,13 @@
#include "char.h"
#include "sectree_manager.h"
#define EMPIRE_NONE 0 // 아무국가 아님
#define EMPIRE_RED 1 // 신수
#define EMPIRE_YELLOW 2 // 천조
#define EMPIRE_BLUE 3 // 진노
#define EMPIRE_NONE 0 // 아무국가 아님
#define EMPIRE_RED 1 // 신수
#define EMPIRE_YELLOW 2 // 천조
#define EMPIRE_BLUE 3 // 진노
#define SIEGE_EVENT_PULSE PASSES_PER_SEC(60*5) // 5분
#define SIEGE_EVENT_PULSE PASSES_PER_SEC(60*5) // 5분
#define GET_CAHR_MANAGER() CHARACTER_MANAGER::instance()
@ -171,7 +171,7 @@ static POSITION s_frog_pos[4][MAX_CASTLE_FROG] = {
};
/* 경비병 경비구역 */
/* 경비병 경비구역 */
struct GUARD_REGION
{
int sx, sy, ex, ey;
@ -247,7 +247,7 @@ EVENTFUNC(castle_siege_event)
info->pulse += SIEGE_EVENT_PULSE;
// 공성 시작후 30분 이내라면 안내만 하자
// 공성 시작후 30분 이내라면 안내만 하자
if (info->pulse < PASSES_PER_SEC(30*60))
{
snprintf(buf, sizeof(buf), LC_TEXT("%s\xBF\xA1\xBC\xAD \xBA\xC0\xC8\xAD\xB8\xA6 \xB5\xD1\xB7\xAF\xBD\xCE\xB0\xED \xC0\xFC\xC5\xF5\xB0\xA1 \xC1\xF8\xC7\xE0\xC1\xDF\xC0\xD4\xB4\xCF\xB4\xD9."),
@ -272,7 +272,7 @@ EVENTFUNC(castle_siege_event)
GET_SIEGE_STATE() = CASTLE_SIEGE_END;
return PASSES_PER_SEC(60*30); // 30분
return PASSES_PER_SEC(60*30); // 30분
}
break;
case CASTLE_SIEGE_END:
@ -331,7 +331,7 @@ EVENTFUNC(castle_stone_event)
if (NULL == sectree_map)
return 0;
/* 15마리씩 2번 소환 */
/* 15마리씩 2번 소환 */
const int SPAWN_COUNT = 15;
if (info->spawn_count < (SPAWN_COUNT * 2))
@ -351,7 +351,7 @@ EVENTFUNC(castle_stone_event)
info->spawn_count += SPAWN_COUNT;
if (info->spawn_count < (SPAWN_COUNT * 2))
return PASSES_PER_SEC(30 * 60); // 30분
return PASSES_PER_SEC(30 * 60); // 30분
else
return 0;
}
@ -598,24 +598,24 @@ void castle_start_siege(int empire, int tower_count)
castle_spawn_tower(empire, tower_count);
/* 공성 타이머 시작 */
/* 공성 타이머 시작 */
{
castle_event_info* info = AllocEventInfo<castle_event_info>();
info->empire = empire;
info->pulse = 0;
GET_SIEGE_EVENT(empire) = event_create(castle_siege_event, info, /*5분*/SIEGE_EVENT_PULSE);
GET_SIEGE_EVENT(empire) = event_create(castle_siege_event, info, /*5분*/SIEGE_EVENT_PULSE);
}
/* 메틴석 소환 타이머 시작 */
/* 메틴석 소환 타이머 시작 */
{
castle_stone_event_info* info = AllocEventInfo<castle_stone_event_info>();
info->spawn_count = 0;
info->empire = empire;
GET_STONE_EVENT(empire) = event_create(castle_stone_event, info, /* 1초 */PASSES_PER_SEC(1));
GET_STONE_EVENT(empire) = event_create(castle_stone_event, info, /* 1초 */PASSES_PER_SEC(1));
}
}
@ -649,7 +649,7 @@ LPCHARACTER castle_spawn_frog(int empire)
int dir = 1;
int map_index = FN_castle_map_index(empire);
/* 황금두꺼비 소환할 곳이 있나? */
/* 황금두꺼비 소환할 곳이 있나? */
POSITION *empty_pos = FN_empty_frog_pos(empire);
if (NULL == empty_pos)
return NULL;
@ -667,7 +667,7 @@ LPCHARACTER castle_spawn_frog(int empire)
{
frog->SetEmpire(empire);
int empty_index = FN_empty_frog_index(empire);
// 스폰성공
// 스폰성공
GET_FROG(empire, empty_index) = frog;
return frog;
}
@ -778,7 +778,7 @@ bool castle_spawn_tower(int empire, int tower_count)
if (NULL == sectree_map)
return false;
// 초기화
// 초기화
DO_ALL_TOWER(i)
{
if (GET_TOWER(empire, i))
@ -786,7 +786,7 @@ bool castle_spawn_tower(int empire, int tower_count)
GET_TOWER(empire, i) = NULL;
}
int spawn_count = std::clamp(tower_count, MIN_CASTLE_TOWER, MAX_CASTLE_TOWER); // 5 ~ 10마리
int spawn_count = std::clamp(tower_count, MIN_CASTLE_TOWER, MAX_CASTLE_TOWER); // 5 ~ 10마리
for (int j = 0; j < spawn_count; ++j)
{
@ -802,7 +802,7 @@ bool castle_spawn_tower(int empire, int tower_count)
return true;
}
/* 경비병리더가 죽으면 단순하게 슬롯만 비운다. */
/* 경비병리더가 죽으면 단순하게 슬롯만 비운다. */
void castle_guard_die(LPCHARACTER ch, LPCHARACTER killer)
{
int empire = ch->GetEmpire();
@ -823,7 +823,7 @@ void castle_guard_die(LPCHARACTER ch, LPCHARACTER killer)
}
/* 황금 두꺼비가 죽으면 killer에게 1천만냥 */
/* 황금 두꺼비가 죽으면 killer에게 1천만냥 */
void castle_frog_die(LPCHARACTER ch, LPCHARACTER killer)
{
if (NULL == ch || NULL == killer)
@ -837,15 +837,15 @@ void castle_frog_die(LPCHARACTER ch, LPCHARACTER killer)
{
GET_FROG(empire, i) = NULL;
killer->PointChange(POINT_GOLD, 10000000 /*1천만*/, true);
//CMonarch::instance().SendtoDBAddMoney(30000000/*3천만*/, killer->GetEmpire(), killer);
killer->PointChange(POINT_GOLD, 10000000 /*1천만*/, true);
//CMonarch::instance().SendtoDBAddMoney(30000000/*3천만*/, killer->GetEmpire(), killer);
castle_save();
return;
}
}
}
/* 봉화가 모두 죽으면(?) 공성전이 끝난다 */
/* 봉화가 모두 죽으면(?) 공성전이 끝난다 */
void castle_tower_die(LPCHARACTER ch, LPCHARACTER killer)
{
char buf[1024] = {0};
@ -929,27 +929,27 @@ bool castle_is_guard_vnum(DWORD vnum)
{
switch (vnum)
{
/* 상급 창경비병 */
/* 상급 창경비병 */
case 11112:
case 11114:
case 11116:
/* 중급 창경비병 */
/* 중급 창경비병 */
case 11106:
case 11108:
case 11110:
/* 하급 창경비병 */
/* 하급 창경비병 */
case 11100:
case 11102:
case 11104:
/* 상급 활경비병 */
/* 상급 활경비병 */
case 11113:
case 11115:
case 11117:
/* 중급 활경비병 */
/* 중급 활경비병 */
case 11107:
case 11109:
case 11111:
/* 하급 활경비병 */
/* 하급 활경비병 */
case 11101:
case 11103:
case 11105:
@ -963,34 +963,34 @@ int castle_cost_of_hiring_guard(DWORD group_vnum)
{
switch (group_vnum)
{
/* 하급 */
case 9501: /* 신수 창경비 */
case 9511: /* 진노 창경비 */
case 9521: /* 천조 창경비 */
/* 하급 */
case 9501: /* 신수 창경비 */
case 9511: /* 진노 창경비 */
case 9521: /* 천조 창경비 */
case 9502: /* 신수 활경비 */
case 9512: /* 진노 활경비 */
case 9522: /* 천조 활경비 */
case 9502: /* 신수 활경비 */
case 9512: /* 진노 활경비 */
case 9522: /* 천조 활경비 */
return (100*10000);
/* 중급 */
case 9503: /* 신수 창경비 */
case 9513: /* 진노 창경비 */
case 9523: /* 천조 창경비 */
/* 중급 */
case 9503: /* 신수 창경비 */
case 9513: /* 진노 창경비 */
case 9523: /* 천조 창경비 */
case 9504: /* 신수 활경비 */
case 9514: /* 진노 활경비 */
case 9524: /* 천조 활경비 */
case 9504: /* 신수 활경비 */
case 9514: /* 진노 활경비 */
case 9524: /* 천조 활경비 */
return (300*10000);
/* 상급 */
case 9505: /* 신수 창경비 */
case 9515: /* 진노 창경비 */
case 9525: /* 천조 창경비 */
/* 상급 */
case 9505: /* 신수 창경비 */
case 9515: /* 진노 창경비 */
case 9525: /* 천조 창경비 */
case 9506: /* 신수 활경비 */
case 9516: /* 진노 활경비 */
case 9526: /* 천조 활경비 */
case 9506: /* 신수 활경비 */
case 9516: /* 진노 활경비 */
case 9526: /* 천조 활경비 */
return (1000*10000);
}
@ -1010,7 +1010,7 @@ bool castle_can_attack(LPCHARACTER ch, LPCHARACTER victim)
if (CASTLE_SIEGE_END == GET_SIEGE_STATE())
{
// 수성에 성공했을때 같은 제국만 봉화를 칠 수 있음
// 수성에 성공했을때 같은 제국만 봉화를 칠 수 있음
if (castle_is_tower_vnum(victim->GetRaceNum()))
{
if (ch->GetEmpire() == victim->GetEmpire())
@ -1020,7 +1020,7 @@ bool castle_can_attack(LPCHARACTER ch, LPCHARACTER victim)
}
}
// 같은 제국은 파괴 불가
// 같은 제국은 파괴 불가
if (ch->GetEmpire() == victim->GetEmpire())
return false;
@ -1044,7 +1044,7 @@ bool castle_frog_to_empire_money(LPCHARACTER ch)
if (false == CMonarch::instance().SendtoDBAddMoney(CASTLE_FROG_PRICE, empire, ch))
return false;
GET_FROG(empire, i) = NULL; // 등록해제
GET_FROG(empire, i) = NULL; // 등록해제
npc->Dead(/*killer*/NULL, /*immediate_dead*/true);
return true;
}

File diff suppressed because it is too large Load Diff

View File

@ -84,13 +84,13 @@ EVENTFUNC(affect_event)
if (!ch->UpdateAffect())
return 0;
else
return passes_per_sec; // 1초
return passes_per_sec; // 1초
}
bool CHARACTER::UpdateAffect()
{
// affect_event 에서 처리할 일은 아니지만, 1초짜리 이벤트에서 처리하는 것이
// 이것 뿐이라 여기서 물약 처리를 한다.
// affect_event 에서 처리할 일은 아니지만, 1초짜리 이벤트에서 처리하는 것이
// 이것 뿐이라 여기서 물약 처리를 한다.
if (GetPoint(POINT_HP_RECOVERY) > 0)
{
if (GetMaxHP() <= GetHP())
@ -146,7 +146,7 @@ bool CHARACTER::UpdateAffect()
AutoRecoveryItemProcess( AFFECT_AUTO_HP_RECOVERY );
AutoRecoveryItemProcess( AFFECT_AUTO_SP_RECOVERY );
// 스테미나 회복
// 스테미나 회복
if (GetMaxStamina() > GetStamina())
{
int iSec = (get_dword_time() - GetStopTime()) / 3000;
@ -155,7 +155,7 @@ bool CHARACTER::UpdateAffect()
}
// ProcessAffect는 affect가 없으면 true를 리턴한다.
// ProcessAffect는 affect가 없으면 true를 리턴한다.
if (ProcessAffect())
if (GetPoint(POINT_HP_RECOVERY) == 0 && GetPoint(POINT_SP_RECOVERY) == 0 && GetStamina() == GetMaxStamina())
{
@ -226,7 +226,7 @@ int CHARACTER::ProcessAffect()
CAffect *pkAff = NULL;
//
// 프리미엄 처리
// 프리미엄 처리
//
for (int i = 0; i <= PREMIUM_MAX_NUM; ++i)
{
@ -300,8 +300,8 @@ int CHARACTER::ProcessAffect()
}
// AFFECT_DURATION_BUG_FIX
// 무한 효과 아이템도 시간을 줄인다.
// 시간을 매우 크게 잡기 때문에 상관 없을 것이라 생각됨.
// 무한 효과 아이템도 시간을 줄인다.
// 시간을 매우 크게 잡기 때문에 상관 없을 것이라 생각됨.
if ( --pkAff->lDuration <= 0 )
{
bEnd = true;
@ -470,7 +470,7 @@ void CHARACTER::LoadAffect(DWORD dwCount, TPacketAffectElement * pElements)
for (DWORD i = 0; i < dwCount; ++i, ++pElements)
{
// 무영진은 로드하지않는다.
// 무영진은 로드하지않는다.
if (pElements->dwType == SKILL_MUYEONG)
continue;
@ -524,7 +524,7 @@ void CHARACTER::LoadAffect(DWORD dwCount, TPacketAffectElement * pElements)
m_bIsLoadedAffect = true;
// 용혼석 셋팅 로드 및 초기화
// 용혼석 셋팅 로드 및 초기화
DragonSoul_Initialize();
}
@ -562,10 +562,10 @@ bool CHARACTER::AddAffect(DWORD dwType, BYTE bApplyOn, int lApplyValue, DWORD dw
}
}
// 이미 있는 효과를 덮어 쓰는 처리
// 이미 있는 효과를 덮어 쓰는 처리
if (pkAff && bOverride)
{
ComputeAffect(pkAff, false); // 일단 효과를 삭제하고
ComputeAffect(pkAff, false); // 일단 효과를 삭제하고
if (GetDesc())
SendAffectRemovePacket(GetDesc(), GetPlayerID(), pkAff->dwType, pkAff->bApplyOn);
@ -573,9 +573,9 @@ bool CHARACTER::AddAffect(DWORD dwType, BYTE bApplyOn, int lApplyValue, DWORD dw
else
{
//
// 새 에펙를 추가
// 새 에펙를 추가
//
// NOTE: 따라서 같은 type 으로도 여러 에펙트를 붙을 수 있다.
// NOTE: 따라서 같은 type 으로도 여러 에펙트를 붙을 수 있다.
//
pkAff = CAffect::Acquire();
m_list_pkAffect.push_back(pkAff);
@ -677,15 +677,15 @@ bool CHARACTER::RemoveAffect(CAffect * pkAff)
ComputeAffect(pkAff, false);
// 백기 버그 수정.
// 백기 버그는 버프 스킬 시전->둔갑->백기 사용(AFFECT_REVIVE_INVISIBLE) 후 바로 공격 할 경우에 발생한다.
// 원인은 둔갑을 시전하는 시점에, 버프 스킬 효과를 무시하고 둔갑 효과만 적용되게 되어있는데,
// 백기 사용 후 바로 공격하면 RemoveAffect가 불리게 되고, ComputePoints하면서 둔갑 효과 + 버프 스킬 효과가 된다.
// ComputePoints에서 둔갑 상태면 버프 스킬 효과 안 먹히도록 하면 되긴 하는데,
// ComputePoints는 광범위하게 사용되고 있어서 큰 변화를 주는 것이 꺼려진다.(어떤 side effect가 발생할지 알기 힘들다.)
// 따라서 AFFECT_REVIVE_INVISIBLE가 RemoveAffect로 삭제되는 경우만 수정한다.
// 시간이 다 되어 백기 효과가 풀리는 경우는 버그가 발생하지 않으므로 그와 똑같이 함.
// (ProcessAffect를 보면 시간이 다 되어서 Affect가 삭제되는 경우, ComputePoints를 부르지 않는다.)
// 백기 버그 수정.
// 백기 버그는 버프 스킬 시전->둔갑->백기 사용(AFFECT_REVIVE_INVISIBLE) 후 바로 공격 할 경우에 발생한다.
// 원인은 둔갑을 시전하는 시점에, 버프 스킬 효과를 무시하고 둔갑 효과만 적용되게 되어있는데,
// 백기 사용 후 바로 공격하면 RemoveAffect가 불리게 되고, ComputePoints하면서 둔갑 효과 + 버프 스킬 효과가 된다.
// ComputePoints에서 둔갑 상태면 버프 스킬 효과 안 먹히도록 하면 되긴 하는데,
// ComputePoints는 광범위하게 사용되고 있어서 큰 변화를 주는 것이 꺼려진다.(어떤 side effect가 발생할지 알기 힘들다.)
// 따라서 AFFECT_REVIVE_INVISIBLE가 RemoveAffect로 삭제되는 경우만 수정한다.
// 시간이 다 되어 백기 효과가 풀리는 경우는 버그가 발생하지 않으므로 그와 똑같이 함.
// (ProcessAffect를 보면 시간이 다 되어서 Affect가 삭제되는 경우, ComputePoints를 부르지 않는다.)
if (AFFECT_REVIVE_INVISIBLE != pkAff->dwType)
{
ComputePoints();
@ -795,41 +795,41 @@ bool CHARACTER::IsGoodAffect(BYTE bAffectType) const
void CHARACTER::RemoveBadAffect()
{
SPDLOG_DEBUG("RemoveBadAffect {}", GetName());
// 독
// 독
RemovePoison();
RemoveFire();
// 스턴 : Value%로 상대방을 5초간 머리 위에 별이 돌아간다. (때리면 1/2 확률로 풀림) AFF_STUN
// 스턴 : Value%로 상대방을 5초간 머리 위에 별이 돌아간다. (때리면 1/2 확률로 풀림) AFF_STUN
RemoveAffect(AFFECT_STUN);
// 슬로우 : Value%로 상대방의 공속/이속 모두 느려진다. 수련도에 따라 달라짐 기술로 사용 한 경우에 AFF_SLOW
// 슬로우 : Value%로 상대방의 공속/이속 모두 느려진다. 수련도에 따라 달라짐 기술로 사용 한 경우에 AFF_SLOW
RemoveAffect(AFFECT_SLOW);
// 투속마령
// 투속마령
RemoveAffect(SKILL_TUSOK);
// 저주
// 저주
//RemoveAffect(SKILL_CURSE);
// 파법술
// 파법술
//RemoveAffect(SKILL_PABUP);
// 기절 : Value%로 상대방을 기절시킨다. 2초 AFF_FAINT
// 기절 : Value%로 상대방을 기절시킨다. 2초 AFF_FAINT
//RemoveAffect(AFFECT_FAINT);
// 다리묶임 : Value%로 상대방의 이동속도를 떨어트린다. 5초간 -40 AFF_WEB
// 다리묶임 : Value%로 상대방의 이동속도를 떨어트린다. 5초간 -40 AFF_WEB
//RemoveAffect(AFFECT_WEB);
// 잠들기 : Value%로 상대방을 10초간 잠재운다. (때리면 풀림) AFF_SLEEP
// 잠들기 : Value%로 상대방을 10초간 잠재운다. (때리면 풀림) AFF_SLEEP
//RemoveAffect(AFFECT_SLEEP);
// 저주 : Value%로 상대방의 공등/방등 모두 떨어트린다. 수련도에 따라 달라짐 기술로 사용 한 경우에 AFF_CURSE
// 저주 : Value%로 상대방의 공등/방등 모두 떨어트린다. 수련도에 따라 달라짐 기술로 사용 한 경우에 AFF_CURSE
//RemoveAffect(AFFECT_CURSE);
// 마비 : Value%로 상대방을 4초간 마비시킨다. AFF_PARA
// 마비 : Value%로 상대방을 4초간 마비시킨다. AFF_PARA
//RemoveAffect(AFFECT_PARALYZE);
// 부동박부 : 무당 기술
// 부동박부 : 무당 기술
//RemoveAffect(SKILL_BUDONG);
}

File diff suppressed because it is too large Load Diff

View File

@ -9,12 +9,12 @@
/*
Return Value
0 : or
1 :
2 :
3 :
0 : or
1 :
2 :
3 :
999 :
999 :
*/
int CHARACTER::ChangeEmpire(BYTE empire)
{
@ -27,7 +27,7 @@ int CHARACTER::ChangeEmpire(BYTE empire)
memset(dwPID, 0, sizeof(dwPID));
{
// 1. 내 계정의 모든 pid를 얻어 온다
// 1. 내 계정의 모든 pid를 얻어 온다
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());
@ -51,8 +51,8 @@ int CHARACTER::ChangeEmpire(BYTE empire)
const int loop = 4;
{
// 2. 각 캐릭터의 길드 정보를 얻어온다.
// 한 캐릭터라도 길드에 가입 되어 있다면, 제국 이동을 할 수 없다.
// 2. 각 캐릭터의 길드 정보를 얻어온다.
// 한 캐릭터라도 길드에 가입 되어 있다면, 제국 이동을 할 수 없다.
DWORD dwGuildID[4];
CGuild * pGuild[4];
SQLMsg * pMsg = NULL;
@ -91,8 +91,8 @@ int CHARACTER::ChangeEmpire(BYTE empire)
}
{
// 3. 각 캐릭터의 결혼 정보를 얻어온다.
// 한 캐릭터라도 결혼 상태라면 제국 이동을 할 수 없다.
// 3. 각 캐릭터의 결혼 정보를 얻어온다.
// 한 캐릭터라도 결혼 상태라면 제국 이동을 할 수 없다.
for (int i = 0; i < loop; ++i)
{
if (marriage::CManager::instance().IsEngagedOrMarried(dwPID[i]) == true)
@ -101,7 +101,7 @@ int CHARACTER::ChangeEmpire(BYTE empire)
}
{
// 4. db의 제국 정보를 업데이트 한다.
// 4. db의 제국 정보를 업데이트 한다.
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());
@ -109,7 +109,7 @@ int CHARACTER::ChangeEmpire(BYTE empire)
if (msg->Get()->uiAffectedRows > 0)
{
// 5. 제국 변경 이력을 추가한다.
// 5. 제국 변경 이력을 추가한다.
SetChangeEmpireCount();
return 999;

View File

@ -5,14 +5,14 @@
#include "DragonSoul.h"
#include "log.h"
// 용혼석 초기화
// 용혼석 on/off는 Affect로 저장되기 때문에,
// 용혼석 Affect가 있다면 덱에 있는 용혼석을 activate해야한다.
// 또한 용혼석 사용 자격은 QuestFlag로 저장해 놓았기 때문에,
// 퀘스트 Flag에서 용혼석 사용 자격을 읽어온다.
// 용혼석 초기화
// 용혼석 on/off는 Affect로 저장되기 때문에,
// 용혼석 Affect가 있다면 덱에 있는 용혼석을 activate해야한다.
// 또한 용혼석 사용 자격은 QuestFlag로 저장해 놓았기 때문에,
// 퀘스트 Flag에서 용혼석 사용 자격을 읽어온다.
// 캐릭터의 affect, quest가 load 되기 전에 DragonSoul_Initialize를 호출하면 안된다.
// affect가 가장 마지막에 로드되어 LoadAffect에서 호출함.
// 캐릭터의 affect, quest가 load 되기 전에 DragonSoul_Initialize를 호출하면 안된다.
// affect가 가장 마지막에 로드되어 LoadAffect에서 호출함.
void CHARACTER::DragonSoul_Initialize()
{
for (int i = INVENTORY_MAX_NUM + WEAR_MAX_NUM; i < DRAGON_SOUL_EQUIP_SLOT_END; i++)
@ -55,7 +55,7 @@ void CHARACTER::DragonSoul_GiveQualification()
}
AddAffect(AFFECT_DRAGON_SOUL_QUALIFIED, APPLY_NONE, 0, AFF_NONE, INFINITE_AFFECT_DURATION, 0, false, false);
//SetQuestFlag("dragon_soul.is_qualified", 1);
//// 자격있다면 POINT_DRAGON_SOUL_IS_QUALIFIED는 무조건 1
//// 자격있다면 POINT_DRAGON_SOUL_IS_QUALIFIED는 무조건 1
//PointChange(POINT_DRAGON_SOUL_IS_QUALIFIED, 1 - GetPoint(POINT_DRAGON_SOUL_IS_QUALIFIED));
}

View File

@ -27,7 +27,7 @@ bool CHARACTER::StartRiding()
return false;
}
// 턱시도 입은 상태의 말 타기 금지
// 턱시도 입은 상태의 말 타기 금지
LPITEM armor = GetWear(WEAR_BODY);
if (armor && (armor->GetVnum() >= 11901 && armor->GetVnum() <= 11904))
@ -57,7 +57,7 @@ bool CHARACTER::StartRiding()
return false;
}
// 소환한 말 없애고
// 소환한 말 없애고
HorseSummon(false);
MountVnum(dwMountVnum);
@ -78,7 +78,7 @@ bool CHARACTER::StopRiding()
DWORD dwOldVnum = GetMountVnum();
MountVnum(0);
// [NOTE] 말에서 내릴 땐 자기가 탔던걸 소환하도록 수정
// [NOTE] 말에서 내릴 땐 자기가 탔던걸 소환하도록 수정
HorseSummon(true, false, dwOldVnum);
}
else
@ -139,14 +139,14 @@ void CHARACTER::HorseSummon(bool bSummon, bool bFromFar, DWORD dwVnum, const cha
{
if ( bSummon )
{
//NOTE : summon했는데 이미 horse가 있으면 아무것도 안한다.
//NOTE : summon했는데 이미 horse가 있으면 아무것도 안한다.
if( m_chHorse != NULL )
return;
if (GetHorseLevel() <= 0)
return;
// 무언가를 타고 있다면 실패
// 무언가를 타고 있다면 실패
if (IsRiding())
return;
@ -183,10 +183,10 @@ void CHARACTER::HorseSummon(bool bSummon, bool bFromFar, DWORD dwVnum, const cha
if (GetHorseHealth() <= 0)
{
// 죽은거처럼 있게 하는 처리
// 죽은거처럼 있게 하는 처리
m_chHorse->SetPosition(POS_DEAD);
// 일정시간있다 사라지게 하자.
// 일정시간있다 사라지게 하자.
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));
@ -239,7 +239,7 @@ void CHARACTER::HorseSummon(bool bSummon, bool bFromFar, DWORD dwVnum, const cha
}
else
{
// 멀어지면서 사라지는 처리 하기
// 멀어지면서 사라지는 처리 하기
chHorse->SetNowWalking(false);
float fx, fy;
chHorse->SetRotation(GetDegreeFromPositionXY(chHorse->GetX(), chHorse->GetY(), GetX(), GetY())+180);
@ -310,7 +310,7 @@ void CHARACTER::SendHorseInfo()
3: 70% < ~ <= 100%
2: 30% < ~ <= 70%
1: 0% < ~ <= 30%
0:
0:
STM
@ -343,8 +343,8 @@ STM
{
ChatPacket(CHAT_TYPE_COMMAND, "horse_state %d %d %d", GetHorseLevel(), iHealthGrade, iStaminaGrade);
// FIX : 클라이언트에 "\xB8\xBB \xBB\xF3\xC5\xC2 \xB9\xF6\xC7\xC1" 아이콘을 표시하지 않을 목적으로 함수 초입에 return함으로써 아래 코드를 무시한다면
// 말을 무한대로 소환하는 무시무시한 버그가 생김.. 정확한 원인은 파악 안해봐서 모름.
// FIX : 클라이언트에 "\xB8\xBB \xBB\xF3\xC5\xC2 \xB9\xF6\xC7\xC1" 아이콘을 표시하지 않을 목적으로 함수 초입에 return함으로써 아래 코드를 무시한다면
// 말을 무한대로 소환하는 무시무시한 버그가 생김.. 정확한 원인은 파악 안해봐서 모름.
m_bSendHorseLevel = GetHorseLevel();
m_bSendHorseHealthGrade = iHealthGrade;
m_bSendHorseStaminaGrade = iStaminaGrade;
@ -366,7 +366,7 @@ bool CHARACTER::CanUseHorseSkill()
if (GetMountVnum() >= 20209 && GetMountVnum() <= 20212)
return true;
//라마단 흑마
//라마단 흑마
if (CMobVnumHelper::IsRamadanBlackHorse(GetMountVnum()))
return true;
}

File diff suppressed because it is too large Load Diff

View File

@ -114,7 +114,7 @@ void CHARACTER_MANAGER::DestroyCharacter(LPCHARACTER ch, const char* file, size_
return; // prevent duplicated destrunction
}
// 던전에 소속된 몬스터는 던전에서도 삭제하도록.
// 던전에 소속된 몬스터는 던전에서도 삭제하도록.
if (ch->IsNPC() && !ch->IsPet() && ch->GetRider() == NULL)
{
if (ch->GetDungeon())
@ -230,7 +230,7 @@ LPCHARACTER CHARACTER_MANAGER::FindPC(const char * name)
LPCHARACTER CHARACTER_MANAGER::SpawnMobRandomPosition(DWORD dwVnum, int lMapIndex)
{
// 왜구 스폰할지말지를 결정할 수 있게함
// 왜구 스폰할지말지를 결정할 수 있게함
{
if (dwVnum == 5001 && !quest::CQuestManager::instance().GetEventFlag("japan_regen"))
{
@ -239,7 +239,7 @@ LPCHARACTER CHARACTER_MANAGER::SpawnMobRandomPosition(DWORD dwVnum, int lMapInde
}
}
// 해태를 스폰할지 말지를 결정할 수 있게 함
// 해태를 스폰할지 말지를 결정할 수 있게 함
{
if (dwVnum == 5002 && !quest::CQuestManager::instance().GetEventFlag("newyear_mob"))
{
@ -248,7 +248,7 @@ LPCHARACTER CHARACTER_MANAGER::SpawnMobRandomPosition(DWORD dwVnum, int lMapInde
}
}
// 광복절 이벤트
// 광복절 이벤트
{
if (dwVnum == 5004 && !quest::CQuestManager::instance().GetEventFlag("independence_day"))
{
@ -448,7 +448,7 @@ LPCHARACTER CHARACTER_MANAGER::SpawnMobRange(DWORD dwVnum, int lMapIndex, int sx
if (!pkMob)
return NULL;
if (pkMob->m_table.bType == CHAR_TYPE_STONE) // 돌은 무조건 SPAWN 모션이 있다.
if (pkMob->m_table.bType == CHAR_TYPE_STONE) // 돌은 무조건 SPAWN 모션이 있다.
bSpawnMotion = true;
int i = 16;
@ -512,7 +512,7 @@ bool CHARACTER_MANAGER::SpawnMoveGroup(DWORD dwVnum, int lMapIndex, int sx, int
if (!tch)
{
if (i == 0) // 못만든 몬스터가 대장일 경우에는 그냥 실패
if (i == 0) // 못만든 몬스터가 대장일 경우에는 그냥 실패
return false;
continue;
@ -596,7 +596,7 @@ LPCHARACTER CHARACTER_MANAGER::SpawnGroup(DWORD dwVnum, int lMapIndex, int sx, i
if (!tch)
{
if (i == 0) // 못만든 몬스터가 대장일 경우에는 그냥 실패
if (i == 0) // 못만든 몬스터가 대장일 경우에는 그냥 실패
return NULL;
continue;
@ -652,11 +652,11 @@ void CHARACTER_MANAGER::Update(int iPulse)
BeginPendingDestroy();
// PC 캐릭터 업데이트
// PC 캐릭터 업데이트
{
if (!m_map_pkPCChr.empty())
{
// 컨테이너 복사
// 컨테이너 복사
CHARACTER_VECTOR v;
v.reserve(m_map_pkPCChr.size());
#ifdef __GNUC__
@ -680,7 +680,7 @@ void CHARACTER_MANAGER::Update(int iPulse)
// for_each_pc(bind2nd(mem_fun(&CHARACTER::UpdateCharacter), iPulse));
}
// 몬스터 업데이트
// 몬스터 업데이트
{
if (!m_set_pkChrState.empty())
{
@ -695,7 +695,7 @@ void CHARACTER_MANAGER::Update(int iPulse)
}
}
// 산타 따로 업데이트
// 산타 따로 업데이트
{
CharacterVectorInteractor i;
@ -706,7 +706,7 @@ void CHARACTER_MANAGER::Update(int iPulse)
}
}
// 1시간에 한번씩 몹 사냥 개수 기록
// 1시간에 한번씩 몹 사냥 개수 기록
if (0 == (iPulse % PASSES_PER_SEC(3600)))
{
for (itertype(m_map_dwMobKillCount) it = m_map_dwMobKillCount.begin(); it != m_map_dwMobKillCount.end(); ++it)
@ -715,11 +715,11 @@ void CHARACTER_MANAGER::Update(int iPulse)
m_map_dwMobKillCount.clear();
}
// 테스트 서버에서는 60초마다 캐릭터 개수를 센다
// 테스트 서버에서는 60초마다 캐릭터 개수를 센다
if (test_server && 0 == (iPulse % PASSES_PER_SEC(60)))
SPDLOG_TRACE("CHARACTER COUNT vid {} pid {}", m_map_pkChrByVID.size(), m_map_pkChrByPID.size());
// 지연된 DestroyCharacter 하기
// 지연된 DestroyCharacter 하기
FlushPendingDestroy();
}
@ -835,7 +835,7 @@ void CHARACTER_MANAGER::RegisterRaceNumMap(LPCHARACTER ch)
{
DWORD dwVnum = ch->GetRaceNum();
if (m_set_dwRegisteredRaceNum.find(dwVnum) != m_set_dwRegisteredRaceNum.end()) // 등록된 번호 이면
if (m_set_dwRegisteredRaceNum.find(dwVnum) != m_set_dwRegisteredRaceNum.end()) // 등록된 번호 이면
{
SPDLOG_TRACE("RegisterRaceNumMap {} {}", ch->GetName(), dwVnum);
m_map_pkChrByRaceNum[dwVnum].insert(ch);
@ -859,7 +859,7 @@ bool CHARACTER_MANAGER::GetCharactersByRaceNum(DWORD dwRaceNum, CharacterVectorI
if (it == m_map_pkChrByRaceNum.end())
return false;
// 컨테이너 복사
// 컨테이너 복사
i = it->second;
return true;
}
@ -1056,8 +1056,8 @@ void CHARACTER_MANAGER::SendScriptToMap(int lMapIndex, const std::string & s)
bool CHARACTER_MANAGER::BeginPendingDestroy()
{
// Begin 이 후에 Begin을 또 하는 경우에 Flush 하지 않는 기능 지원을 위해
// 이미 시작되어있으면 false 리턴 처리
// Begin 이 후에 Begin을 또 하는 경우에 Flush 하지 않는 기능 지원을 위해
// 이미 시작되어있으면 false 리턴 처리
if (m_bUsePendingDestroy)
return false;
@ -1069,7 +1069,7 @@ void CHARACTER_MANAGER::FlushPendingDestroy()
{
using namespace std;
m_bUsePendingDestroy = false; // 플래그를 먼저 설정해야 실제 Destroy 처리가 됨
m_bUsePendingDestroy = false; // 플래그를 먼저 설정해야 실제 Destroy 처리가 됨
if (!m_set_pkChrPendingDestroy.empty())
{

View File

@ -9,7 +9,7 @@
/////////////////////////////////////////////////////////////////////////////
// QUICKSLOT HANDLING
/////////////////////////////////////////////////////////////////////////////
void CHARACTER::SyncQuickslot(BYTE bType, BYTE bOldPos, BYTE bNewPos) // bNewPos == 255 면 DELETE
void CHARACTER::SyncQuickslot(BYTE bType, BYTE bOldPos, BYTE bNewPos) // bNewPos == 255 면 DELETE
{
if (bOldPos == bNewPos)
return;
@ -121,7 +121,7 @@ bool CHARACTER::SwapQuickslot(BYTE a, BYTE b)
if (a >= QUICKSLOT_MAX_NUM || b >= QUICKSLOT_MAX_NUM)
return false;
// 퀵 슬롯 자리를 서로 바꾼다.
// 퀵 슬롯 자리를 서로 바꾼다.
quickslot = m_quickslot[a];
m_quickslot[a] = m_quickslot[b];

View File

@ -6,7 +6,7 @@
#include "affect.h"
#include "locale_service.h"
// 독
// 독
const int poison_damage_rate[MOB_RANK_MAX_NUM] =
{
80, 50, 40, 30, 25, 1
@ -135,7 +135,7 @@ EVENTFUNC(fire_event)
/*
LEVEL에 ..
LEVEL에 ..
+8 0%
+7 5%
@ -184,7 +184,7 @@ void CHARACTER::AttackedByPoison(LPCHARACTER pkAttacker)
if (m_pkPoisonEvent)
return;
if (m_bHasPoisoned && !IsPC()) // 몬스터는 독이 한번만 걸린다.
if (m_bHasPoisoned && !IsPC()) // 몬스터는 독이 한번만 걸린다.
return;
if (pkAttacker && pkAttacker->GetLevel() < GetLevel())
@ -201,7 +201,7 @@ void CHARACTER::AttackedByPoison(LPCHARACTER pkAttacker)
/*if (IsImmune(IMMUNE_POISON))
return;*/
// 독 내성 굴림 실패, 독에 걸렸다!
// 독 내성 굴림 실패, 독에 걸렸다!
m_bHasPoisoned = true;
AddAffect(AFFECT_POISON, POINT_NONE, 0, AFF_POISON, POISON_LENGTH + 1, 0, true);

View File

@ -62,7 +62,7 @@ void CHARACTER::SetSkillNextReadTime(DWORD dwVnum, time_t time)
bool TSkillUseInfo::HitOnce(DWORD dwVnum)
{
// 쓰지도않았으면 때리지도 못한다.
// 쓰지도않았으면 때리지도 못한다.
if (!bUsed)
return false;
@ -97,7 +97,7 @@ bool TSkillUseInfo::UseSkill(bool isGrandMaster, DWORD vid, DWORD dwCooltime, in
this->isGrandMaster = isGrandMaster;
DWORD dwCur = get_dword_time();
// 아직 쿨타임이 끝나지 않았다.
// 아직 쿨타임이 끝나지 않았다.
if (bUsed && dwNextSkillUsableTime > dwCur)
{
SPDLOG_DEBUG("cooltime is not over delta {}", dwNextSkillUsableTime - dwCur);
@ -280,7 +280,7 @@ bool CHARACTER::LearnGrandMasterSkill(DWORD dwSkillVnum)
{
if (FindAffect(AFFECT_SKILL_NO_BOOK_DELAY))
{
// 주안술서 사용중에는 시간 제한 무시
// 주안술서 사용중에는 시간 제한 무시
RemoveAffect(AFFECT_SKILL_NO_BOOK_DELAY);
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xC1\xD6\xBE\xC8\xBC\xFA\xBC\xAD\xB8\xA6 \xC5\xEB\xC7\xD8 \xC1\xD6\xC8\xAD\xC0\xD4\xB8\xB6\xBF\xA1\xBC\xAD \xBA\xFC\xC1\xAE\xB3\xAA\xBF\xD4\xBD\xC0\xB4\xCF\xB4\xD9."));
}
@ -293,7 +293,7 @@ bool CHARACTER::LearnGrandMasterSkill(DWORD dwSkillVnum)
}
*/
// bType이 0이면 처음부터 책으로 수련 가능
// bType이 0이면 처음부터 책으로 수련 가능
if (pkSk->dwType == 0)
{
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB1\xD7\xB7\xA3\xB5\xE5 \xB8\xB6\xBD\xBA\xC5\xCD \xBC\xF6\xB7\xC3\xC0\xBB \xC7\xD2 \xBC\xF6 \xBE\xF8\xB4\xC2 \xBD\xBA\xC5\xB3\xC0\xD4\xB4\xCF\xB4\xD9."));
@ -316,7 +316,7 @@ bool CHARACTER::LearnGrandMasterSkill(DWORD dwSkillVnum)
strTrainSkill = os.str();
}
// 여기서 확률을 계산합니다.
// 여기서 확률을 계산합니다.
BYTE bLastLevel = GetSkillLevel(dwSkillVnum);
int idx = std::min(9, GetSkillLevel(dwSkillVnum) - 30);
@ -438,7 +438,7 @@ bool CHARACTER::LearnSkillByBook(DWORD dwSkillVnum, BYTE bProb)
}
}
// bType이 0이면 처음부터 책으로 수련 가능
// bType이 0이면 처음부터 책으로 수련 가능
if (pkSk->dwType != 0)
{
if (GetSkillMasterType(dwSkillVnum) != SKILL_MASTER)
@ -457,7 +457,7 @@ bool CHARACTER::LearnSkillByBook(DWORD dwSkillVnum, BYTE bProb)
{
if (FindAffect(AFFECT_SKILL_NO_BOOK_DELAY))
{
// 주안술서 사용중에는 시간 제한 무시
// 주안술서 사용중에는 시간 제한 무시
RemoveAffect(AFFECT_SKILL_NO_BOOK_DELAY);
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xC1\xD6\xBE\xC8\xBC\xFA\xBC\xAD\xB8\xA6 \xC5\xEB\xC7\xD8 \xC1\xD6\xC8\xAD\xC0\xD4\xB8\xB6\xBF\xA1\xBC\xAD \xBA\xFC\xC1\xAE\xB3\xAA\xBF\xD4\xBD\xC0\xB4\xCF\xB4\xD9."));
}
@ -469,7 +469,7 @@ bool CHARACTER::LearnSkillByBook(DWORD dwSkillVnum, BYTE bProb)
}
}
// 여기서 확률을 계산합니다.
// 여기서 확률을 계산합니다.
BYTE bLastLevel = GetSkillLevel(dwSkillVnum);
if (bProb != 0)
@ -527,7 +527,7 @@ bool CHARACTER::LearnSkillByBook(DWORD dwSkillVnum, BYTE bProb)
if (Random::get(1, 100) > percent)
{
// 책읽기에 성공
// 책읽기에 성공
if (read_count >= need_bookcount)
{
SkillLevelUp(dwSkillVnum, SKILL_UP_BY_BOOK);
@ -564,7 +564,7 @@ bool CHARACTER::LearnSkillByBook(DWORD dwSkillVnum, BYTE bProb)
}
else
{
// 사용자의 퀘스트 정보 로드 실패
// 사용자의 퀘스트 정보 로드 실패
}
}
// INTERNATIONAL_VERSION
@ -721,7 +721,7 @@ void CHARACTER::SkillLevelUp(DWORD dwVnum, BYTE bMethod)
if (!IsLearnableSkill(dwVnum))
return;
// 그랜드 마스터는 퀘스트로만 수행가능
// 그랜드 마스터는 퀘스트로만 수행가능
if (pkSk->dwType != 0)
{
switch (GetSkillMasterType(pkSk->dwVnum))
@ -738,7 +738,7 @@ void CHARACTER::SkillLevelUp(DWORD dwVnum, BYTE bMethod)
if (bMethod == SKILL_UP_BY_POINT)
{
// 마스터가 아닌 상태에서만 수련가능
// 마스터가 아닌 상태에서만 수련가능
if (GetSkillMasterType(pkSk->dwVnum) != SKILL_NORMAL)
return;
@ -747,7 +747,7 @@ void CHARACTER::SkillLevelUp(DWORD dwVnum, BYTE bMethod)
}
else if (bMethod == SKILL_UP_BY_BOOK)
{
if (pkSk->dwType != 0) // 직업에 속하지 않았거나 포인트로 올릴수 없는 스킬은 처음부터 책으로 배울 수 있다.
if (pkSk->dwType != 0) // 직업에 속하지 않았거나 포인트로 올릴수 없는 스킬은 처음부터 책으로 배울 수 있다.
if (GetSkillMasterType(pkSk->dwVnum) != SKILL_MASTER)
return;
}
@ -801,11 +801,11 @@ void CHARACTER::SkillLevelUp(DWORD dwVnum, BYTE bMethod)
if (pkSk->dwType != 0)
{
// 갑자기 그레이드 업하는 코딩
// 갑자기 그레이드 업하는 코딩
switch (GetSkillMasterType(pkSk->dwVnum))
{
case SKILL_NORMAL:
// 번섭은 스킬 업그레이드 17~20 사이 랜덤 마스터 수련
// 번섭은 스킬 업그레이드 17~20 사이 랜덤 마스터 수련
if (GetSkillLevel(pkSk->dwVnum) >= 17)
{
if (GetQuestFlag("reset_scroll.force_to_master_skill") > 0)
@ -863,7 +863,7 @@ void CHARACTER::ResetSkill()
if (NULL == m_pSkillLevels)
return;
// 보조 스킬은 리셋시키지 않는다
// 보조 스킬은 리셋시키지 않는다
std::vector<std::pair<DWORD, TPlayerSkill> > vec;
size_t count = sizeof(s_adwSubSkillVnums) / sizeof(s_adwSubSkillVnums[0]);
@ -994,7 +994,7 @@ EVENTFUNC(ChainLightningEvent)
SPDLOG_DEBUG("chainlighting event {}", pkChr->GetName());
if (pkChrVictim->GetParty()) // 파티 먼저
if (pkChrVictim->GetParty()) // 파티 먼저
{
pkTarget = pkChrVictim->GetParty()->GetNextOwnership(NULL, pkChrVictim->GetX(), pkChrVictim->GetY());
if (pkTarget == pkChrVictim || !Random::get(0, 2) || pkChr->GetChainLightingExcept().find(pkTarget) != pkChr->GetChainLightingExcept().end())
@ -1090,7 +1090,7 @@ struct FuncSplashDamage
}
if (m_pkChr->IsPC())
// 길드 스킬은 쿨타임 처리를 하지 않는다.
// 길드 스킬은 쿨타임 처리를 하지 않는다.
if (!(m_pkSk->dwVnum >= GUILD_SKILL_START && m_pkSk->dwVnum <= GUILD_SKILL_END))
if (!m_bDisableCooltime && m_pInfo && !m_pInfo->HitOnce(m_pkSk->dwVnum) && m_pkSk->dwVnum != SKILL_MUYEONG)
{
@ -1159,7 +1159,7 @@ struct FuncSplashDamage
m_pkSk->SetPointVar("chain", m_pkChr->GetChainLightningIndex());
m_pkChr->IncChainLightningIndex();
bool bUnderEunhyung = m_pkChr->GetAffectedEunhyung() > 0; // 이건 왜 여기서 하지??
bool bUnderEunhyung = m_pkChr->GetAffectedEunhyung() > 0; // 이건 왜 여기서 하지??
m_pkSk->SetPointVar("ek", m_pkChr->GetAffectedEunhyung()*1./100);
//m_pkChr->ClearAffectedEunhyung();
@ -1241,11 +1241,11 @@ struct FuncSplashDamage
if (m_pkChr->IsPC() && m_pkChr->m_SkillUseInfo[m_pkSk->dwVnum].GetMainTargetVID() != (DWORD) pkChrVictim->GetVID())
{
// 데미지 감소
// 데미지 감소
iDam = (int) (iDam * m_pkSk->kSplashAroundDamageAdjustPoly.Eval());
}
// TODO 스킬에 따른 데미지 타입 기록해야한다.
// TODO 스킬에 따른 데미지 타입 기록해야한다.
EDamageType dt = DAMAGE_TYPE_NONE;
switch (m_pkSk->bSkillAttrType)
@ -1268,7 +1268,7 @@ struct FuncSplashDamage
case WEAPON_TWO_HANDED:
iDam = iDam * (100 - pkChrVictim->GetPoint(POINT_RESIST_TWOHAND)) / 100;
// 양손검 페널티 10%
// 양손검 페널티 10%
//iDam = iDam * 95 / 100;
break;
@ -1293,8 +1293,8 @@ struct FuncSplashDamage
case SKILL_ATTR_TYPE_RANGE:
dt = DAMAGE_TYPE_RANGE;
// 으아아아악
// 예전에 적용안했던 버그가 있어서 방어력 계산을 다시하면 유저가 난리남
// 으아아아악
// 예전에 적용안했던 버그가 있어서 방어력 계산을 다시하면 유저가 난리남
//iDam -= pkChrVictim->GetPoint(POINT_DEF_GRADE);
iDam = iDam * (100 - pkChrVictim->GetPoint(POINT_RESIST_BOW)) / 100;
break;
@ -1302,8 +1302,8 @@ struct FuncSplashDamage
case SKILL_ATTR_TYPE_MAGIC:
dt = DAMAGE_TYPE_MAGIC;
iDam = CalcAttBonus(m_pkChr, pkChrVictim, iDam);
// 으아아아악
// 예전에 적용안했던 버그가 있어서 방어력 계산을 다시하면 유저가 난리남
// 으아아아악
// 예전에 적용안했던 버그가 있어서 방어력 계산을 다시하면 유저가 난리남
//iDam -= pkChrVictim->GetPoint(POINT_MAGIC_DEF_GRADE);
iDam = iDam * (100 - pkChrVictim->GetPoint(POINT_RESIST_MAGIC)) / 100;
break;
@ -1314,13 +1314,13 @@ struct FuncSplashDamage
}
//
// 20091109 독일 스킬 속성 요청 작업
// 기존 스킬 테이블에 SKILL_FLAG_WIND, SKILL_FLAG_ELEC, SKILL_FLAG_FIRE를 가진 스킬이
// 전혀 없었으므로 몬스터의 RESIST_WIND, RESIST_ELEC, RESIST_FIRE도 사용되지 않고 있었다.
// 20091109 독일 스킬 속성 요청 작업
// 기존 스킬 테이블에 SKILL_FLAG_WIND, SKILL_FLAG_ELEC, SKILL_FLAG_FIRE를 가진 스킬이
// 전혀 없었으므로 몬스터의 RESIST_WIND, RESIST_ELEC, RESIST_FIRE도 사용되지 않고 있었다.
//
// PvP와 PvE밸런스 분리를 위해 의도적으로 NPC만 적용하도록 했으며 기존 밸런스와 차이점을
// 느끼지 못하기 위해 mob_proto의 RESIST_MAGIC을 RESIST_WIND, RESIST_ELEC, RESIST_FIRE로
// 복사하였다.
// PvP와 PvE밸런스 분리를 위해 의도적으로 NPC만 적용하도록 했으며 기존 밸런스와 차이점을
// 느끼지 못하기 위해 mob_proto의 RESIST_MAGIC을 RESIST_WIND, RESIST_ELEC, RESIST_FIRE로
// 복사하였다.
//
if (pkChrVictim->IsNPC())
{
@ -1627,7 +1627,7 @@ EVENTFUNC(skill_gwihwan_event)
{
PIXEL_POSITION pos;
// 성공
// 성공
if (SECTREE_MANAGER::instance().GetRecallPositionByEmpire(ch->GetMapIndex(), ch->GetEmpire(), pos))
{
SPDLOG_DEBUG("Recall: {} {} {} -> {} {}", ch->GetName(), ch->GetX(), ch->GetY(), pos.x, pos.y);
@ -1641,7 +1641,7 @@ EVENTFUNC(skill_gwihwan_event)
}
else
{
//실패
//실패
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB1\xCD\xC8\xAF\xBF\xA1 \xBD\xC7\xC6\xD0\xC7\xCF\xBF\xB4\xBD\xC0\xB4\xCF\xB4\xD9."));
}
return 0;
@ -1666,11 +1666,11 @@ int CHARACTER::ComputeSkillAtPosition(DWORD dwVnum, const PIXEL_POSITION& posTar
SPDLOG_TRACE("ComputeSkillAtPosition {} vnum {} x {} y {} level {}",
GetName(), dwVnum, posTarget.x, posTarget.y, bSkillLevel);
// 나에게 쓰는 스킬은 내 위치를 쓴다.
// 나에게 쓰는 스킬은 내 위치를 쓴다.
//if (IS_SET(pkSk->dwFlag, SKILL_FLAG_SELFONLY))
// posTarget = GetXYZ();
// 스플래쉬가 아닌 스킬은 주위이면 이상하다
// 스플래쉬가 아닌 스킬은 주위이면 이상하다
if (!IS_SET(pkSk->dwFlag, SKILL_FLAG_SPLASH))
return BATTLE_NONE;
@ -1769,7 +1769,7 @@ int CHARACTER::ComputeSkillAtPosition(DWORD dwVnum, const PIXEL_POSITION& posTar
if (IS_SET(pkSk->dwFlag, SKILL_FLAG_ATTACK | SKILL_FLAG_USE_MELEE_DAMAGE | SKILL_FLAG_USE_MAGIC_DAMAGE))
{
//
// 공격 스킬일 경우
// 공격 스킬일 경우
//
bool bAdded = false;
@ -1794,7 +1794,7 @@ int CHARACTER::ComputeSkillAtPosition(DWORD dwVnum, const PIXEL_POSITION& posTar
int iDur = (int) pkSk->kDurationPoly.Eval();
if (IsPC())
if (!(dwVnum >= GUILD_SKILL_START && dwVnum <= GUILD_SKILL_END)) // 길드 스킬은 쿨타임 처리를 하지 않는다.
if (!(dwVnum >= GUILD_SKILL_START && dwVnum <= GUILD_SKILL_END)) // 길드 스킬은 쿨타임 처리를 하지 않는다.
if (!m_bDisableCooltime && !m_SkillUseInfo[dwVnum].HitOnce(dwVnum) && dwVnum != SKILL_MUYEONG)
{
return BATTLE_NONE;
@ -1884,7 +1884,7 @@ int CHARACTER::ComputeSkillAtPosition(DWORD dwVnum, const PIXEL_POSITION& posTar
if (iDur > 0)
{
iDur += GetPoint(POINT_PARTY_BUFFER_BONUS);
// AffectFlag가 없거나, toggle 하는 것이 아니라면..
// AffectFlag가 없거나, toggle 하는 것이 아니라면..
pkSk->kDurationSPCostPoly.SetVar("k", k/*bSkillLevel*/);
AddAffect(pkSk->dwVnum,
@ -1939,13 +1939,13 @@ int CHARACTER::ComputeSkillAtPosition(DWORD dwVnum, const PIXEL_POSITION& posTar
}
}
// bSkillLevel 인자가 0이 아닐 경우에는 m_abSkillLevels를 사용하지 않고 강제로
// bSkillLevel로 계산한다.
// bSkillLevel 인자가 0이 아닐 경우에는 m_abSkillLevels를 사용하지 않고 강제로
// bSkillLevel로 계산한다.
int CHARACTER::ComputeSkill(DWORD dwVnum, LPCHARACTER pkVictim, BYTE bSkillLevel)
{
const bool bCanUseHorseSkill = CanUseHorseSkill();
// 말을 타고있지만 스킬은 사용할 수 없는 상태라면 return
// 말을 타고있지만 스킬은 사용할 수 없는 상태라면 return
if (false == bCanUseHorseSkill && true == IsRiding())
return BATTLE_NONE;
@ -1967,7 +1967,7 @@ int CHARACTER::ComputeSkill(DWORD dwVnum, LPCHARACTER pkVictim, BYTE bSkillLevel
return BATTLE_NONE;
// 상대방에게 쓰는 것이 아니면 나에게 써야 한다.
// 상대방에게 쓰는 것이 아니면 나에게 써야 한다.
if (IS_SET(pkSk->dwFlag, SKILL_FLAG_SELFONLY))
pkVictim = this;
@ -2135,7 +2135,7 @@ int CHARACTER::ComputeSkill(DWORD dwVnum, LPCHARACTER pkVictim, BYTE bSkillLevel
if (IsPC())
if (!(dwVnum >= GUILD_SKILL_START && dwVnum <= GUILD_SKILL_END)) // 길드 스킬은 쿨타임 처리를 하지 않는다.
if (!(dwVnum >= GUILD_SKILL_START && dwVnum <= GUILD_SKILL_END)) // 길드 스킬은 쿨타임 처리를 하지 않는다.
if (!m_bDisableCooltime && !m_SkillUseInfo[dwVnum].HitOnce(dwVnum) && dwVnum != SKILL_MUYEONG)
{
return BATTLE_NONE;
@ -2248,7 +2248,7 @@ int CHARACTER::ComputeSkill(DWORD dwVnum, LPCHARACTER pkVictim, BYTE bSkillLevel
if (iDur > 0)
{
iDur += GetPoint(POINT_PARTY_BUFFER_BONUS);
// AffectFlag가 없거나, toggle 하는 것이 아니라면..
// AffectFlag가 없거나, toggle 하는 것이 아니라면..
pkSk->kDurationSPCostPoly.SetVar("k", k/*bSkillLevel*/);
if (pkSk->bPointOn2 != POINT_NONE)
@ -2428,7 +2428,7 @@ bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaste
return true;
}
// 말을 타고있지만 스킬은 사용할 수 없는 상태라면 return false
// 말을 타고있지만 스킬은 사용할 수 없는 상태라면 return false
if (false == bCanUseHorseSkill && true == IsRiding())
return false;
@ -2474,7 +2474,7 @@ bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaste
}
m_SkillUseInfo[dwVnum].SetMainTargetVID(pkVictim->GetVID());
// DASH 상태의 탄환격은 공격기술
// DASH 상태의 탄환격은 공격기술
ComputeSkill(dwVnum, pkVictim);
RemoveAffect(dwVnum);
return true;
@ -2492,7 +2492,7 @@ bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaste
return true;
}
// Toggle 할 때는 SP를 쓰지 않음 (SelfOnly로 구분)
// Toggle 할 때는 SP를 쓰지 않음 (SelfOnly로 구분)
if ((0 != pkSk->dwAffectFlag || pkSk->dwVnum == SKILL_MUYEONG) && (pkSk->dwFlag & SKILL_FLAG_TOGGLE) && RemoveAffect(pkSk->dwVnum))
{
return true;
@ -2506,7 +2506,7 @@ bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaste
pkSk->SetPointVar("k", k);
pkSk->kSplashAroundDamageAdjustPoly.SetVar("k", k);
// 쿨타임 체크
// 쿨타임 체크
pkSk->kCooldownPoly.SetVar("k", k);
int iCooltime = (int) pkSk->kCooldownPoly.Eval();
int lMaxHit = pkSk->lMaxHit ? pkSk->lMaxHit : -1;
@ -2570,7 +2570,7 @@ bool CHARACTER::UseSkill(DWORD dwVnum, LPCHARACTER pkVictim, bool bUseGrandMaste
if (pkSk->dwVnum == SKILL_MUYEONG || pkSk->IsChargeSkill() && !IsAffectFlag(AFF_TANHWAN_DASH) && !pkVictim)
{
// 처음 사용하는 무영진은 자신에게 Affect를 붙인다.
// 처음 사용하는 무영진은 자신에게 Affect를 붙인다.
pkVictim = this;
}
@ -2643,7 +2643,7 @@ int CHARACTER::GetSkillMasterType(DWORD dwVnum) const
int CHARACTER::GetSkillPower(DWORD dwVnum, BYTE bLevel) const
{
// 인어반지 아이템
// 인어반지 아이템
if (dwVnum >= SKILL_LANGUAGE1 && dwVnum <= SKILL_LANGUAGE3 && IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
{
return 100;
@ -2748,16 +2748,16 @@ void CHARACTER::SkillLearnWaitMoreTimeMessage(DWORD ms)
ChatPacket(CHAT_TYPE_TALKING, "%s", LC_TEXT("\xB8\xF6 \xBC\xD3\xC0\xCC \xB6\xDF\xB0\xCC\xB1\xBA. \xC7\xCF\xC1\xF6\xB8\xB8 \xBE\xC6\xC1\xD6 \xC6\xED\xBE\xC8\xC7\xD8. \xC0\xCC\xB4\xEB\xB7\xCE \xB1\xE2\xB8\xA6 \xBE\xC8\xC1\xA4\xBD\xC3\xC5\xB0\xC0\xDA."));
else if (ms < 5 * 60)
ChatPacket(CHAT_TYPE_TALKING, "%s", LC_TEXT("\xB1\xD7\xB7\xA1, \xC3\xB5\xC3\xB5\xC8\xF7. \xC1\xBB\xB4\xF5 \xC3\xB5\xC3\xB5\xC8\xF7, \xB1\xD7\xB7\xAF\xB3\xAA \xB8\xB7\xC8\xFB \xBE\xF8\xC0\xCC \xBA\xFC\xB8\xA3\xB0\xD4!"));
else if (ms < 10 * 60) // 10분
else if (ms < 10 * 60) // 10분
ChatPacket(CHAT_TYPE_TALKING, "%s", LC_TEXT("\xB1\xD7\xB7\xA1, \xC0\xCC \xB4\xC0\xB3\xA6\xC0\xCC\xBE\xDF. \xC3\xBC\xB3\xBB\xBF\xA1 \xB1\xE2\xB0\xA1 \xBE\xC6\xC1\xD6 \xC3\xE6\xB8\xB8\xC7\xD8."));
else if (ms < 30 * 60) // 30분
else if (ms < 30 * 60) // 30분
{
ChatPacket(CHAT_TYPE_TALKING, "%s", LC_TEXT("\xB4\xD9 \xC0\xD0\xBE\xFA\xB4\xD9! \xC0\xCC\xC1\xA6 \xBA\xF1\xB1\xDE\xBF\xA1 \xC0\xFB\xC7\xF4\xC0\xD6\xB4\xC2 \xB4\xEB\xB7\xCE \xC0\xFC\xBD\xC5\xBF\xA1 \xB1\xE2\xB8\xA6 \xB5\xB9\xB8\xAE\xB1\xE2\xB8\xB8 \xC7\xCF\xB8\xE9,"));
ChatPacket(CHAT_TYPE_TALKING, "%s", LC_TEXT("\xB1\xD7\xB0\xCD\xC0\xB8\xB7\xCE \xBC\xF6\xB7\xC3\xC0\xBA \xB3\xA1\xB3\xAD \xB0\xC5\xBE\xDF!"));
}
else if (ms < 1 * 3600) // 1시간
else if (ms < 1 * 3600) // 1시간
ChatPacket(CHAT_TYPE_TALKING, "%s", LC_TEXT("\xC0\xCC\xC1\xA6 \xC3\xA5\xC0\xC7 \xB8\xB6\xC1\xF6\xB8\xB7 \xC0\xE5\xC0\xCC\xBE\xDF! \xBC\xF6\xB7\xC3\xC0\xC7 \xB3\xA1\xC0\xCC \xB4\xAB\xBF\xA1 \xBA\xB8\xC0\xCC\xB0\xED \xC0\xD6\xBE\xEE!"));
else if (ms < 2 * 3600) // 2시간
else if (ms < 2 * 3600) // 2시간
ChatPacket(CHAT_TYPE_TALKING, "%s", LC_TEXT("\xBE\xF3\xB8\xB6 \xBE\xC8 \xB3\xB2\xBE\xD2\xBE\xEE! \xC1\xB6\xB1\xDD\xB8\xB8 \xB4\xF5!"));
else if (ms < 3 * 3600)
ChatPacket(CHAT_TYPE_TALKING, "%s", LC_TEXT("\xC1\xC1\xBE\xD2\xBE\xEE! \xC1\xB6\xB1\xDD\xB8\xB8 \xB4\xF5 \xC0\xD0\xC0\xB8\xB8\xE9 \xB3\xA1\xC0\xCC\xB4\xD9!"));
@ -3138,10 +3138,10 @@ bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
static DWORD s_anMotion2SkillVnumList[MOTION_MAX_NUM][SKILL_LIST_MAX_COUNT] =
{
// 스킬수 무사스킬ID 자객스킬ID 수라스킬ID 무당스킬ID
// 스킬수 무사스킬ID 자객스킬ID 수라스킬ID 무당스킬ID
{ 0, 0, 0, 0, 0 }, // 0
// 1번 직군 기본 스킬
// 1번 직군 기본 스킬
{ 4, 1, 31, 61, 91 }, // 1
{ 4, 2, 32, 62, 92 }, // 2
{ 4, 3, 33, 63, 93 }, // 3
@ -3150,9 +3150,9 @@ bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
{ 4, 6, 36, 66, 96 }, // 6
{ 0, 0, 0, 0, 0 }, // 7
{ 0, 0, 0, 0, 0 }, // 8
// 1번 직군 기본 스킬 끝
// 1번 직군 기본 스킬 끝
// 여유분
// 여유분
{ 0, 0, 0, 0, 0 }, // 9
{ 0, 0, 0, 0, 0 }, // 10
{ 0, 0, 0, 0, 0 }, // 11
@ -3160,9 +3160,9 @@ bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
{ 0, 0, 0, 0, 0 }, // 13
{ 0, 0, 0, 0, 0 }, // 14
{ 0, 0, 0, 0, 0 }, // 15
// 여유분 끝
// 여유분 끝
// 2번 직군 기본 스킬
// 2번 직군 기본 스킬
{ 4, 16, 46, 76, 106 }, // 16
{ 4, 17, 47, 77, 107 }, // 17
{ 4, 18, 48, 78, 108 }, // 18
@ -3171,14 +3171,14 @@ bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
{ 4, 21, 51, 81, 111 }, // 21
{ 0, 0, 0, 0, 0 }, // 22
{ 0, 0, 0, 0, 0 }, // 23
// 2번 직군 기본 스킬 끝
// 2번 직군 기본 스킬 끝
// 여유분
// 여유분
{ 0, 0, 0, 0, 0 }, // 24
{ 0, 0, 0, 0, 0 }, // 25
// 여유분 끝
// 여유분 끝
// 1번 직군 마스터 스킬
// 1번 직군 마스터 스킬
{ 4, 1, 31, 61, 91 }, // 26
{ 4, 2, 32, 62, 92 }, // 27
{ 4, 3, 33, 63, 93 }, // 28
@ -3187,9 +3187,9 @@ bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
{ 4, 6, 36, 66, 96 }, // 31
{ 0, 0, 0, 0, 0 }, // 32
{ 0, 0, 0, 0, 0 }, // 33
// 1번 직군 마스터 스킬 끝
// 1번 직군 마스터 스킬 끝
// 여유분
// 여유분
{ 0, 0, 0, 0, 0 }, // 34
{ 0, 0, 0, 0, 0 }, // 35
{ 0, 0, 0, 0, 0 }, // 36
@ -3197,9 +3197,9 @@ bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
{ 0, 0, 0, 0, 0 }, // 38
{ 0, 0, 0, 0, 0 }, // 39
{ 0, 0, 0, 0, 0 }, // 40
// 여유분 끝
// 여유분 끝
// 2번 직군 마스터 스킬
// 2번 직군 마스터 스킬
{ 4, 16, 46, 76, 106 }, // 41
{ 4, 17, 47, 77, 107 }, // 42
{ 4, 18, 48, 78, 108 }, // 43
@ -3208,14 +3208,14 @@ bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
{ 4, 21, 51, 81, 111 }, // 46
{ 0, 0, 0, 0, 0 }, // 47
{ 0, 0, 0, 0, 0 }, // 48
// 2번 직군 마스터 스킬 끝
// 2번 직군 마스터 스킬 끝
// 여유분
// 여유분
{ 0, 0, 0, 0, 0 }, // 49
{ 0, 0, 0, 0, 0 }, // 50
// 여유분 끝
// 여유분 끝
// 1번 직군 그랜드 마스터 스킬
// 1번 직군 그랜드 마스터 스킬
{ 4, 1, 31, 61, 91 }, // 51
{ 4, 2, 32, 62, 92 }, // 52
{ 4, 3, 33, 63, 93 }, // 53
@ -3224,9 +3224,9 @@ bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
{ 4, 6, 36, 66, 96 }, // 56
{ 0, 0, 0, 0, 0 }, // 57
{ 0, 0, 0, 0, 0 }, // 58
// 1번 직군 그랜드 마스터 스킬 끝
// 1번 직군 그랜드 마스터 스킬 끝
// 여유분
// 여유분
{ 0, 0, 0, 0, 0 }, // 59
{ 0, 0, 0, 0, 0 }, // 60
{ 0, 0, 0, 0, 0 }, // 61
@ -3234,9 +3234,9 @@ bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
{ 0, 0, 0, 0, 0 }, // 63
{ 0, 0, 0, 0, 0 }, // 64
{ 0, 0, 0, 0, 0 }, // 65
// 여유분 끝
// 여유분 끝
// 2번 직군 그랜드 마스터 스킬
// 2번 직군 그랜드 마스터 스킬
{ 4, 16, 46, 76, 106 }, // 66
{ 4, 17, 47, 77, 107 }, // 67
{ 4, 18, 48, 78, 108 }, // 68
@ -3245,14 +3245,14 @@ bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
{ 4, 21, 51, 81, 111 }, // 71
{ 0, 0, 0, 0, 0 }, // 72
{ 0, 0, 0, 0, 0 }, // 73
// 2번 직군 그랜드 마스터 스킬 끝
// 2번 직군 그랜드 마스터 스킬 끝
//여유분
//여유분
{ 0, 0, 0, 0, 0 }, // 74
{ 0, 0, 0, 0, 0 }, // 75
// 여유분 끝
// 여유분 끝
// 1번 직군 퍼펙트 마스터 스킬
// 1번 직군 퍼펙트 마스터 스킬
{ 4, 1, 31, 61, 91 }, // 76
{ 4, 2, 32, 62, 92 }, // 77
{ 4, 3, 33, 63, 93 }, // 78
@ -3261,9 +3261,9 @@ bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
{ 4, 6, 36, 66, 96 }, // 81
{ 0, 0, 0, 0, 0 }, // 82
{ 0, 0, 0, 0, 0 }, // 83
// 1번 직군 퍼펙트 마스터 스킬 끝
// 1번 직군 퍼펙트 마스터 스킬 끝
// 여유분
// 여유분
{ 0, 0, 0, 0, 0 }, // 84
{ 0, 0, 0, 0, 0 }, // 85
{ 0, 0, 0, 0, 0 }, // 86
@ -3271,9 +3271,9 @@ bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
{ 0, 0, 0, 0, 0 }, // 88
{ 0, 0, 0, 0, 0 }, // 89
{ 0, 0, 0, 0, 0 }, // 90
// 여유분 끝
// 여유분 끝
// 2번 직군 퍼펙트 마스터 스킬
// 2번 직군 퍼펙트 마스터 스킬
{ 4, 16, 46, 76, 106 }, // 91
{ 4, 17, 47, 77, 107 }, // 92
{ 4, 18, 48, 78, 108 }, // 93
@ -3282,23 +3282,23 @@ bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
{ 4, 21, 51, 81, 111 }, // 96
{ 0, 0, 0, 0, 0 }, // 97
{ 0, 0, 0, 0, 0 }, // 98
// 2번 직군 퍼펙트 마스터 스킬 끝
// 2번 직군 퍼펙트 마스터 스킬 끝
// 여유분
// 여유분
{ 0, 0, 0, 0, 0 }, // 99
{ 0, 0, 0, 0, 0 }, // 100
// 여유분 끝
// 여유분 끝
// 길드 스킬
// 길드 스킬
{ 1, 152, 0, 0, 0}, // 101
{ 1, 153, 0, 0, 0}, // 102
{ 1, 154, 0, 0, 0}, // 103
{ 1, 155, 0, 0, 0}, // 104
{ 1, 156, 0, 0, 0}, // 105
{ 1, 157, 0, 0, 0}, // 106
// 길드 스킬 끝
// 길드 스킬 끝
// 여유분
// 여유분
{ 0, 0, 0, 0, 0}, // 107
{ 0, 0, 0, 0, 0}, // 108
{ 0, 0, 0, 0, 0}, // 109
@ -3313,13 +3313,13 @@ bool CHARACTER::IsUsableSkillMotion(DWORD dwMotionIndex) const
{ 0, 0, 0, 0, 0}, // 118
{ 0, 0, 0, 0, 0}, // 119
{ 0, 0, 0, 0, 0}, // 120
// 여유분 끝
// 여유분 끝
// 승마 스킬
// 승마 스킬
{ 2, 137, 140, 0, 0}, // 121
{ 1, 138, 0, 0, 0}, // 122
{ 1, 139, 0, 0, 0}, // 123
// 승마 스킬 끝
// 승마 스킬 끝
};
if (dwMotionIndex >= MOTION_MAX_NUM)
@ -3473,7 +3473,7 @@ bool CHARACTER::CanUseSkill(DWORD dwSkillVnum) const
if (true == IsRiding())
{
//마운트 탈것중 고급말만 스킬 사용가능
//마운트 탈것중 고급말만 스킬 사용가능
if(GetMountVnum())
{
if( GetMountVnum() < 20209 && GetMountVnum() > 20212)

View File

@ -63,7 +63,7 @@ namespace
!pkChr->IsAffectFlag(AFF_WAR_FLAG2) &&
!pkChr->IsAffectFlag(AFF_WAR_FLAG3))
{
// 우리편 깃발일 경우
// 우리편 깃발일 경우
if ((DWORD) m_pkChr->GetPoint(POINT_STAT) == pkChr->GetGuild()->GetID())
{
CWarMap * pMap = pkChr->GetWarMap();
@ -72,8 +72,8 @@ namespace
if (!pMap || !pMap->GetTeamIndex(pkChr->GetGuild()->GetID(), idx))
return;
// 우리편 기지에 깃발이 없을 때만 깃발을 뽑는다. 안그러면 기지에 있는 깃발을
// 가만히 두고 싶은데도 뽑힐수가 있으므로..
// 우리편 기지에 깃발이 없을 때만 깃발을 뽑는다. 안그러면 기지에 있는 깃발을
// 가만히 두고 싶은데도 뽑힐수가 있으므로..
if (!pMap->IsFlagOnBase(idx))
{
m_pkChrFind = pkChr;
@ -82,7 +82,7 @@ namespace
}
else
{
// 상대편 깃발인 경우 무조건 뽑는다.
// 상대편 깃발인 경우 무조건 뽑는다.
m_pkChrFind = pkChr;
m_iMinDistance = iDist;
}
@ -186,7 +186,7 @@ namespace
LPCHARACTER pkChr = (LPCHARACTER) ent;
// 일단 PC 공격안함
// 일단 PC 공격안함
if (pkChr->IsPC())
return;
@ -202,7 +202,7 @@ namespace
pkChr->IsAffectFlag(AFF_REVIVE_INVISIBLE))
return;
// 왜구는 패스
// 왜구는 패스
if (pkChr->GetRaceNum() == 5001)
return;
@ -285,7 +285,7 @@ void CHARACTER::CowardEscape()
for (int iDistIdx = 2; iDistIdx >= 0; --iDistIdx)
for (int iTryCount = 0; iTryCount < 8; ++iTryCount)
{
SetRotation(Random::get(0, 359)); // 방향은 랜덤으로 설정
SetRotation(Random::get(0, 359)); // 방향은 랜덤으로 설정
float fx, fy;
float fDist = Random::get(iDist[iDistIdx], iDist[iDistIdx+1]);
@ -367,7 +367,7 @@ void CHARACTER::StateIdle()
}
else if (IsWarp() || IsGoto())
{
// 워프는 이벤트로 처리
// 워프는 이벤트로 처리
m_dwStateDuration = 60 * passes_per_sec;
return;
}
@ -375,7 +375,7 @@ void CHARACTER::StateIdle()
if (IsPC())
return;
// NPC 처리
// NPC 처리
if (!IsMonster())
{
__StateIdle_NPC();
@ -506,7 +506,7 @@ void CHARACTER::__StateIdle_NPC()
MonsterChat(MONSTER_CHAT_WAIT);
m_dwStateDuration = PASSES_PER_SEC(5);
// 펫 시스템의 Idle 처리는 기존 거의 모든 종류의 캐릭터들이 공유해서 사용하는 상태머신이 아닌 CPetActor::Update에서 처리함.
// 펫 시스템의 Idle 처리는 기존 거의 모든 종류의 캐릭터들이 공유해서 사용하는 상태머신이 아닌 CPetActor::Update에서 처리함.
if (IsPet())
return;
else if (IsGuardNPC())
@ -531,21 +531,21 @@ void CHARACTER::__StateIdle_NPC()
}
else
{
if (GetRaceNum() == xmas::MOB_SANTA_VNUM) // 산타
if (GetRaceNum() == xmas::MOB_SANTA_VNUM) // 산타
{
if (get_dword_time() > m_dwPlayStartTime)
{
int next_warp_time = 2 * 1000; // 2초
int next_warp_time = 2 * 1000; // 2초
m_dwPlayStartTime = get_dword_time() + next_warp_time;
// 시간이 넘었으니 워프합시다.
// 시간이 넘었으니 워프합시다.
/*
*
*
const int WARP_MAP_INDEX_NUM = 4;
static const int c_lWarpMapIndexs[WARP_MAP_INDEX_NUM] = {61, 62, 63, 64};
*/
// 신선자 노해용
// 신선자 노해용
const int WARP_MAP_INDEX_NUM = 7;
static const int c_lWarpMapIndexs[WARP_MAP_INDEX_NUM] = { 61, 62, 63, 64, 3, 23, 43 };
int lNextMapIndex;
@ -553,7 +553,7 @@ void CHARACTER::__StateIdle_NPC()
if (map_allow_find(lNextMapIndex))
{
// 이곳입니다.
// 이곳입니다.
M2_DESTROY_CHARACTER(this);
int iNextSpawnDelay = 0;
if (LC_IsYMIR())
@ -565,7 +565,7 @@ void CHARACTER::__StateIdle_NPC()
}
else
{
// 다른 서버 입니다.
// 다른 서버 입니다.
TPacketGGXmasWarpSanta p;
p.bHeader = HEADER_GG_XMAS_WARP_SANTA;
p.bChannel = g_bChannel;
@ -579,7 +579,7 @@ void CHARACTER::__StateIdle_NPC()
if (!IS_SET(m_pointsInstant.dwAIFlag, AIFLAG_NOMOVE))
{
//
// 이 곳 저 곳 이동한다.
// 이 곳 저 곳 이동한다.
//
LPCHARACTER pkChrProtege = GetProtege();
@ -594,14 +594,14 @@ void CHARACTER::__StateIdle_NPC()
if (!Random::get(0, 6))
{
SetRotation(Random::get(0, 359)); // 방향은 랜덤으로 설정
SetRotation(Random::get(0, 359)); // 방향은 랜덤으로 설정
float fx, fy;
float fDist = Random::get(200, 400);
GetDeltaByDegree(GetRotation(), fDist, &fx, &fy);
// 느슨한 못감 속성 체크; 최종 위치와 중간 위치가 갈수없다면 가지 않는다.
// 느슨한 못감 속성 체크; 최종 위치와 중간 위치가 갈수없다면 가지 않는다.
if (!(SECTREE_MANAGER::instance().IsMovablePosition(GetMapIndex(), GetX() + (int) fx, GetY() + (int) fy)
&& SECTREE_MANAGER::instance().IsMovablePosition(GetMapIndex(), GetX() + (int) fx / 2, GetY() + (int) fy / 2)))
return;
@ -627,7 +627,7 @@ void CHARACTER::__StateIdle_Monster()
if (IsCoward())
{
// 겁쟁이 몬스터는 도망만 다닙니다.
// 겁쟁이 몬스터는 도망만 다닙니다.
if (!IsDead())
CowardEscape();
@ -653,16 +653,16 @@ void CHARACTER::__StateIdle_Monster()
if (!victim || victim->IsBuilding())
{
// 돌 보호 처리
// 돌 보호 처리
if (m_pkChrStone)
{
victim = m_pkChrStone->GetNearestVictim(m_pkChrStone);
}
// 선공 몬스터 처리
// 선공 몬스터 처리
else if (!no_wander && IsAggressive())
{
if (GetMapIndex() == 61 && quest::CQuestManager::instance().GetEventFlag("xmas_tree"));
// 서한산에서 나무가 있으면 선공하지않는다.
// 서한산에서 나무가 있으면 선공하지않는다.
else
victim = FindVictim(this, m_pkMobData->m_table.wAggressiveSight);
}
@ -683,7 +683,7 @@ void CHARACTER::__StateIdle_Monster()
LPCHARACTER pkChrProtege = GetProtege();
// 보호할 것(돌, 파티장)에게로 부터 멀다면 따라간다.
// 보호할 것(돌, 파티장)에게로 부터 멀다면 따라간다.
if (pkChrProtege)
{
if (DISTANCE_APPROX(GetX() - pkChrProtege->GetX(), GetY() - pkChrProtege->GetY()) > 1000)
@ -697,26 +697,26 @@ void CHARACTER::__StateIdle_Monster()
}
//
// 그냥 왔다리 갔다리 한다.
// 그냥 왔다리 갔다리 한다.
//
if (!no_wander && !IS_SET(m_pointsInstant.dwAIFlag, AIFLAG_NOMOVE))
{
if (!Random::get(0, 6))
{
SetRotation(Random::get(0, 359)); // 방향은 랜덤으로 설정
SetRotation(Random::get(0, 359)); // 방향은 랜덤으로 설정
float fx, fy;
float fDist = Random::get(300, 700);
GetDeltaByDegree(GetRotation(), fDist, &fx, &fy);
// 느슨한 못감 속성 체크; 최종 위치와 중간 위치가 갈수없다면 가지 않는다.
// 느슨한 못감 속성 체크; 최종 위치와 중간 위치가 갈수없다면 가지 않는다.
if (!(SECTREE_MANAGER::instance().IsMovablePosition(GetMapIndex(), GetX() + (int) fx, GetY() + (int) fy)
&& SECTREE_MANAGER::instance().IsMovablePosition(GetMapIndex(), GetX() + (int) fx/2, GetY() + (int) fy/2)))
return;
// NOTE: 몬스터가 IDLE 상태에서 주변을 서성거릴 때, 현재 무조건 뛰어가게 되어 있음. (절대로 걷지 않음)
// 그래픽 팀에서 몬스터가 걷는 모습도 보고싶다고 해서 임시로 특정확률로 걷거나 뛰게 함. (게임의 전반적인 느낌이 틀려지기 때문에 일단 테스트 모드에서만 작동)
// NOTE: 몬스터가 IDLE 상태에서 주변을 서성거릴 때, 현재 무조건 뛰어가게 되어 있음. (절대로 걷지 않음)
// 그래픽 팀에서 몬스터가 걷는 모습도 보고싶다고 해서 임시로 특정확률로 걷거나 뛰게 함. (게임의 전반적인 느낌이 틀려지기 때문에 일단 테스트 모드에서만 작동)
if (g_test_server)
{
if (Random::get(0, 100) < 60)
@ -745,13 +745,13 @@ bool __CHARACTER_GotoNearTarget(LPCHARACTER self, LPCHARACTER victim)
{
case BATTLE_TYPE_RANGE:
case BATTLE_TYPE_MAGIC:
// 마법사나 궁수는 공격 거리의 80%까지 가서 공격을 시작한다.
// 마법사나 궁수는 공격 거리의 80%까지 가서 공격을 시작한다.
if (self->Follow(victim, self->GetMobAttackRange() * 8 / 10))
return true;
break;
default:
// 나머지는 90%?
// 나머지는 90%?
if (self->Follow(victim, self->GetMobAttackRange() * 9 / 10))
return true;
}
@ -781,7 +781,7 @@ void CHARACTER::StateMove()
LPCHARACTER victim = GetExchange()->GetCompany()->GetOwner();
int iDist = DISTANCE_APPROX(GetX() - victim->GetX(), GetY() - victim->GetY());
// 거리 체크
// 거리 체크
if (iDist >= EXCHANGE_MAX_DISTANCE)
{
GetExchange()->Cancel();
@ -789,17 +789,17 @@ void CHARACTER::StateMove()
}
}
// 스테미나가 0 이상이어야 한다.
// 스테미나가 0 이상이어야 한다.
if (IsPC())
{
if (IsWalking() && GetStamina() < GetMaxStamina())
{
// 5초 후 부터 스테미너 증가
// 5초 후 부터 스테미너 증가
if (get_dword_time() - GetWalkStartTime() > 5000)
PointChange(POINT_STAMINA, GetMaxStamina() / 1);
}
// 전투 중이면서 뛰는 중이면
// 전투 중이면서 뛰는 중이면
if (!IsWalking() && !IsRiding())
if ((get_dword_time() - GetLastAttackTime()) < 20000)
{
@ -817,7 +817,7 @@ void CHARACTER::StateMove()
if (GetStamina() <= 0)
{
// 스테미나가 모자라 걸어야함
// 스테미나가 모자라 걸어야함
SetStamina(0);
SetNowWalking(true);
StopStaminaConsume();
@ -838,7 +838,7 @@ void CHARACTER::StateMove()
if (g_test_server)
{
// 몬스터가 적을 쫓아가는 것이면 무조건 뛰어간다.
// 몬스터가 적을 쫓아가는 것이면 무조건 뛰어간다.
SetNowWalking(false);
}
}
@ -847,10 +847,10 @@ void CHARACTER::StateMove()
{
LPCHARACTER victim = GetVictim();
// 거대 거북
// 거대 거북
if (GetRaceNum() == 2191 && Random::get(1, 20) == 1 && get_dword_time() - m_pkMobInst->m_dwLastWarpTime > 1000)
{
// 워프 테스트
// 워프 테스트
float fx, fy;
GetDeltaByDegree(victim->GetRotation(), 400, &fx, &fy);
int new_x = victim->GetX() + (int)fx;
@ -864,7 +864,7 @@ void CHARACTER::StateMove()
return;
}
// TODO 방향전환을 해서 덜 바보가 되자!
// TODO 방향전환을 해서 덜 바보가 되자!
if (Random::get(0, 3) == 0)
{
if (__CHARACTER_GotoNearTarget(this, victim))
@ -1005,7 +1005,7 @@ void CHARACTER::StateBattle()
{
if (!GetParty())
{
// 서몬해서 채워둘 파티를 만들어 둡니다.
// 서몬해서 채워둘 파티를 만들어 둡니다.
CPartyManager::instance().CreateParty(this);
}
@ -1015,7 +1015,7 @@ void CHARACTER::StateBattle()
if (bPct && pParty->CountMemberByVnum(GetSummonVnum()) < SUMMON_MONSTER_COUNT)
{
MonsterLog("\xBA\xCE\xC7\xCF \xB8\xF3\xBD\xBA\xC5\xCD \xBC\xD2\xC8\xAF!");
// 모자라는 녀석을 불러내 채웁시다.
// 모자라는 녀석을 불러내 채웁시다.
int sx = GetX() - 300;
int sy = GetY() - 300;
int ex = GetX() + 300;
@ -1035,12 +1035,12 @@ void CHARACTER::StateBattle()
float fDist = DISTANCE_APPROX(GetX() - victim->GetX(), GetY() - victim->GetY());
if (fDist >= 4000.0f) // 40미터 이상 멀어지면 포기
if (fDist >= 4000.0f) // 40미터 이상 멀어지면 포기
{
MonsterLog("\xC5\xB8\xB0\xD9\xC0\xCC \xB8\xD6\xBE\xEE\xBC\xAD \xC6\xF7\xB1\xE2");
SetVictim(NULL);
// 보호할 것(돌, 파티장) 주변으로 간다.
// 보호할 것(돌, 파티장) 주변으로 간다.
if (pkChrProtege)
if (DISTANCE_APPROX(GetX() - pkChrProtege->GetX(), GetY() - pkChrProtege->GetY()) > 1000)
Follow(pkChrProtege, Random::get(150, 400));
@ -1059,7 +1059,7 @@ void CHARACTER::StateBattle()
if (2493 == m_pkMobData->m_table.dwVnum)
{
// 수룡(2493) 특수 처리
// 수룡(2493) 특수 처리
m_dwStateDuration = BlueDragon_StateBattle(this);
return;
}
@ -1067,7 +1067,7 @@ void CHARACTER::StateBattle()
DWORD dwCurTime = get_dword_time();
DWORD dwDuration = CalculateDuration(GetLimitPoint(POINT_ATT_SPEED), 2000);
if ((dwCurTime - m_dwLastAttackTime) < dwDuration) // 2초 마다 공격해야 한다.
if ((dwCurTime - m_dwLastAttackTime) < dwDuration) // 2초 마다 공격해야 한다.
{
m_dwStateDuration = std::max<int>(1, (passes_per_sec * (dwDuration - (dwCurTime - m_dwLastAttackTime)) / 1000));
return;
@ -1084,7 +1084,7 @@ void CHARACTER::StateBattle()
SetGodSpeed(true);
//
// 몹 스킬 처리
// 몹 스킬 처리
//
if (HasMobSkill())
{
@ -1109,11 +1109,11 @@ void CHARACTER::StateBattle()
}
}
if (!Attack(victim)) // 공격 실패라면? 왜 실패했지? TODO
if (!Attack(victim)) // 공격 실패라면? 왜 실패했지? TODO
m_dwStateDuration = passes_per_sec / 2;
else
{
// 적을 바라보게 만든다.
// 적을 바라보게 만든다.
SetRotationToXY(victim->GetX(), victim->GetY());
SendMovePacket(FUNC_ATTACK, 0, GetX(), GetY(), 0, dwCurTime);
@ -1166,15 +1166,15 @@ void CHARACTER::StateFlagBase()
void CHARACTER::StateHorse()
{
float START_FOLLOW_DISTANCE = 400.0f; // 이 거리 이상 떨어지면 쫓아가기 시작함
float START_RUN_DISTANCE = 700.0f; // 이 거리 이상 떨어지면 뛰어서 쫓아감.
int MIN_APPROACH = 150; // 최소 접근 거리
int MAX_APPROACH = 300; // 최대 접근 거리
float START_FOLLOW_DISTANCE = 400.0f; // 이 거리 이상 떨어지면 쫓아가기 시작함
float START_RUN_DISTANCE = 700.0f; // 이 거리 이상 떨어지면 뛰어서 쫓아감.
int MIN_APPROACH = 150; // 최소 접근 거리
int MAX_APPROACH = 300; // 최대 접근 거리
DWORD STATE_DURATION = (DWORD)PASSES_PER_SEC(0.5); // 상태 지속 시간
DWORD STATE_DURATION = (DWORD)PASSES_PER_SEC(0.5); // 상태 지속 시간
bool bDoMoveAlone = true; // 캐릭터와 가까이 있을 때 혼자 여기저기 움직일건지 여부 -_-;
bool bRun = true; // 뛰어야 하나?
bool bDoMoveAlone = true; // 캐릭터와 가까이 있을 때 혼자 여기저기 움직일건지 여부 -_-;
bool bRun = true; // 뛰어야 하나?
if (IsDead())
return;
@ -1183,7 +1183,7 @@ void CHARACTER::StateHorse()
LPCHARACTER victim = GetRider();
// ! 아님 // 대상이 없는 경우 소환자가 직접 나를 클리어할 것임
// ! 아님 // 대상이 없는 경우 소환자가 직접 나를 클리어할 것임
if (!victim)
{
M2_DESTROY_CHARACTER(this);
@ -1197,7 +1197,7 @@ void CHARACTER::StateHorse()
if (fDist >= START_FOLLOW_DISTANCE)
{
if (fDist > START_RUN_DISTANCE)
SetNowWalking(!bRun); // NOTE: 함수 이름보고 멈추는건줄 알았는데 SetNowWalking(false) 하면 뛰는거임.. -_-;
SetNowWalking(!bRun); // NOTE: 함수 이름보고 멈추는건줄 알았는데 SetNowWalking(false) 하면 뛰는거임.. -_-;
Follow(victim, Random::get(MIN_APPROACH, MAX_APPROACH));
@ -1208,14 +1208,14 @@ void CHARACTER::StateHorse()
// wondering-.-
m_dwLastAttackTime = get_dword_time() + Random::get(5000, 12000);
SetRotation(Random::get(0, 359)); // 방향은 랜덤으로 설정
SetRotation(Random::get(0, 359)); // 방향은 랜덤으로 설정
float fx, fy;
float fDist = Random::get(200, 400);
GetDeltaByDegree(GetRotation(), fDist, &fx, &fy);
// 느슨한 못감 속성 체크; 최종 위치와 중간 위치가 갈수없다면 가지 않는다.
// 느슨한 못감 속성 체크; 최종 위치와 중간 위치가 갈수없다면 가지 않는다.
if (!(SECTREE_MANAGER::instance().IsMovablePosition(GetMapIndex(), GetX() + (int) fx, GetY() + (int) fy)
&& SECTREE_MANAGER::instance().IsMovablePosition(GetMapIndex(), GetX() + (int) fx/2, GetY() + (int) fy/2)))
return;

View File

@ -187,7 +187,7 @@ ACMD(do_effect);
ACMD(do_threeway_war_info );
ACMD(do_threeway_war_myinfo );
//
//군주 전용기능
//군주 전용기능
ACMD(do_monarch_warpto);
ACMD(do_monarch_transfer);
ACMD(do_monarch_info);
@ -196,7 +196,7 @@ ACMD(do_monarch_tax);
ACMD(do_monarch_mob);
ACMD(do_monarch_notice);
//군주 관리 기능
//군주 관리 기능
ACMD(do_rmcandidacy);
ACMD(do_setmonarch);
ACMD(do_rmmonarch);
@ -204,10 +204,10 @@ ACMD(do_rmmonarch);
ACMD(do_hair);
//gift notify quest command
ACMD(do_gift);
// 큐브관련
// 큐브관련
ACMD(do_inventory);
ACMD(do_cube);
// 공성전
// 공성전
ACMD(do_siege);
ACMD(do_temp);
ACMD(do_frog);
@ -235,7 +235,7 @@ ACMD(do_ride);
ACMD(do_get_item_id_list);
ACMD(do_set_socket);
#ifdef __AUCTION__
// temp_auction 임시
// temp_auction 임시
ACMD(do_get_auction_list);
ACMD (do_get_my_auction_list);
ACMD (do_get_my_purchase_list);
@ -255,21 +255,21 @@ ACMD (do_cancel_sale);
ACMD (do_rebid);
ACMD (do_bid_cancel);
#endif
// 코스츔 상태보기 및 벗기
// 코스츔 상태보기 및 벗기
ACMD(do_costume);
ACMD(do_set_stat);
// 무적
// 무적
ACMD (do_can_dead);
ACMD (do_full_set);
// 직군과 레벨에 따른 최고 아이템
// 직군과 레벨에 따른 최고 아이템
ACMD (do_item_full_set);
// 직군에 따른 최고 옵션의 속성 셋팅
// 직군에 따른 최고 옵션의 속성 셋팅
ACMD (do_attr_full_set);
// 모든 스킬 마스터
// 모든 스킬 마스터
ACMD (do_all_skill_master);
// 아이템 착용. icon이 없어 클라에서 확인 할 수 없는 아이템 착용을 위해 만듦.
// 아이템 착용. icon이 없어 클라에서 확인 할 수 없는 아이템 착용을 위해 만듦.
ACMD (do_use_item);
ACMD (do_dragon_soul);
ACMD (do_ds_list);
@ -277,7 +277,7 @@ ACMD (do_clear_affect);
struct command_info cmd_info[] =
{
{ "!RESERVED!", NULL, 0, POS_DEAD, GM_IMPLEMENTOR }, /* 반드시 이 것이 처음이어야 한다. */
{ "!RESERVED!", NULL, 0, POS_DEAD, GM_IMPLEMENTOR }, /* 반드시 이 것이 처음이어야 한다. */
{ "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 },
@ -298,7 +298,7 @@ struct command_info cmd_info[] =
{ "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 }, /* 몹의 위치와 방향을 설정해 소환 /mob_ld vnum x y dir */
{ "mob_ld", do_mob_ld, 0, POS_DEAD, GM_HIGH_WIZARD }, /* 몹의 위치와 방향을 설정해 소환 /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 },
@ -546,7 +546,7 @@ struct command_info cmd_info[] =
{ "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 임시
// auction 임시
{ "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 },
@ -586,7 +586,7 @@ struct command_info cmd_info[] =
{ "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 } /* 반드시 이 것이 마지막이어야 한다. */
{ "\n", NULL, 0, POS_DEAD, GM_IMPLEMENTOR } /* 반드시 이 것이 마지막이어야 한다. */
};
void interpreter_set_privilege(const char *cmd, int lvl)
@ -609,7 +609,7 @@ 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 넣을 자리 확보
// \0 넣을 자리 확보
dest_len -= 1;
while (src_len-- && *tmp)
@ -644,7 +644,7 @@ void interpret_command(LPCHARACTER ch, const char * argument, size_t len)
return ;
}
char cmd[128 + 1]; // buffer overflow 문제가 생기지 않도록 일부러 길이를 짧게 잡음
char cmd[128 + 1]; // buffer overflow 문제가 생기지 않도록 일부러 길이를 짧게 잡음
char new_line[256 + 1];
const char * line;
int icmd;
@ -661,7 +661,7 @@ void interpret_command(LPCHARACTER ch, const char * argument, size_t len)
{
if (cmd_info[icmd].command_pointer == do_cmd)
{
if (!strcmp(cmd_info[icmd].command, cmd)) // do_cmd는 모든 명령어를 쳐야 할 수 있다.
if (!strcmp(cmd_info[icmd].command, cmd)) // do_cmd는 모든 명령어를 쳐야 할 수 있다.
break;
}
else if (!strncmp(cmd_info[icmd].command, cmd, cmdlen))
@ -713,7 +713,7 @@ void interpret_command(LPCHARACTER ch, const char * argument, size_t len)
return;
}
if (strncmp("phase", cmd_info[icmd].command, 5) != 0) // 히든 명령어 처리
if (strncmp("phase", cmd_info[icmd].command, 5) != 0) // 히든 명령어 처리
SPDLOG_DEBUG("COMMAND: {}: {}", ch->GetName(), cmd_info[icmd].command);
((*cmd_info[icmd].command_pointer) (ch, line, icmd, cmd_info[icmd].subcmd));

View File

@ -108,11 +108,11 @@ ACMD(do_emotion_allow)
bool CHARACTER_CanEmotion(CHARACTER& rch)
{
// <EFBFBD><EFBFBD>ȥ<EFBFBD><EFBFBD> <20>ʿ<EFBFBD><CABF><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD>.
// 결혼식 맵에서는 사용할 수 있다.
if (marriage::WeddingManager::instance().IsWeddingMap(rch.GetMapIndex()))
return true;
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD>.
// 열정의 가면 착용시 사용할 수 있다.
if (rch.IsEquipUniqueItem(UNIQUE_ITEM_EMOTION_MASK))
return true;
@ -246,7 +246,7 @@ ACMD(do_emotion)
if (len < 0 || len >= (int) sizeof(chatbuf))
len = sizeof(chatbuf) - 1;
++len; // \0 <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
++len; // \0 문자 포함
TPacketGCChat pack_chat;
pack_chat.header = HEADER_GC_CHAT;

View File

@ -46,7 +46,7 @@ ACMD(do_user_horse_ride)
if (ch->IsHorseRiding() == false)
{
// 말이 아닌 다른탈것을 타고있다.
// 말이 아닌 다른탈것을 타고있다.
if (ch->GetMountVnum())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xC0\xCC\xB9\xCC \xC5\xBB\xB0\xCD\xC0\xBB \xC0\xCC\xBF\xEB\xC1\xDF\xC0\xD4\xB4\xCF\xB4\xD9."));
@ -86,7 +86,7 @@ ACMD(do_user_horse_back)
ACMD(do_user_horse_feed)
{
// 개인상점을 연 상태에서는 말 먹이를 줄 수 없다.
// 개인상점을 연 상태에서는 말 먹이를 줄 수 없다.
if (ch->GetMyShop())
return;
@ -397,7 +397,7 @@ ACMD(do_mount)
char arg1[256];
struct action_mount_param param;
// 이미 타고 있으면
// 이미 타고 있으면
if (ch->GetMountingChr())
{
char arg2[256];
@ -488,7 +488,7 @@ ACMD(do_restart)
{
if (ch->IsHack())
{
//성지 맵일경우에는 체크 하지 않는다.
//성지 맵일경우에는 체크 하지 않는다.
if (false == CThreeWayWar::instance().IsSungZiMapIndex(ch->GetMapIndex()))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xBE\xC6\xC1\xF7 \xC0\xE7\xBD\xC3\xC0\xDB \xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9. (%d\xC3\xCA \xB3\xB2\xC0\xBD)"), iTimeToDead - (180 - g_nPortalLimitTime));
@ -505,13 +505,13 @@ ACMD(do_restart)
}
//PREVENT_HACK
//DESC : 창고, 교환 창 후 포탈을 사용하는 버그에 이용될수 있어서
// 쿨타임을 추가
//DESC : 창고, 교환 창 후 포탈을 사용하는 버그에 이용될수 있어서
// 쿨타임을 추가
if (subcmd == SCMD_RESTART_TOWN)
{
if (ch->IsHack())
{
//길드맵, 성지맵에서는 체크 하지 않는다.
//길드맵, 성지맵에서는 체크 하지 않는다.
if ((!ch->GetWarMap() || ch->GetWarMap()->GetType() == GUILD_WAR_TYPE_FLAG) ||
false == CThreeWayWar::instance().IsSungZiMapIndex(ch->GetMapIndex()))
{
@ -535,7 +535,7 @@ ACMD(do_restart)
ch->StartRecoveryEvent();
//FORKED_LOAD
//DESC: 삼거리 전투시 부활을 할경우 맵의 입구가 아닌 삼거리 전투의 시작지점으로 이동하게 된다.
//DESC: 삼거리 전투시 부활을 할경우 맵의 입구가 아닌 삼거리 전투의 시작지점으로 이동하게 된다.
if (1 == quest::CQuestManager::instance().GetEventFlag("threeway_war"))
{
if (subcmd == SCMD_RESTART_TOWN || subcmd == SCMD_RESTART_HERE)
@ -552,7 +552,7 @@ ACMD(do_restart)
return;
}
//성지
//성지
if (true == CThreeWayWar::instance().IsSungZiMapIndex(ch->GetMapIndex()))
{
if (CThreeWayWar::instance().GetReviveTokenForPlayer(ch->GetPlayerID()) <= 0)
@ -867,7 +867,7 @@ ACMD(do_skillup)
}
//
// @version 05/06/20 Bang2ni - 커맨드 처리 Delegate to CHARACTER class
// @version 05/06/20 Bang2ni - 커맨드 처리 Delegate to CHARACTER class
//
ACMD(do_safebox_close)
{
@ -875,7 +875,7 @@ ACMD(do_safebox_close)
}
//
// @version 05/06/20 Bang2ni - 커맨드 처리 Delegate to CHARACTER class
// @version 05/06/20 Bang2ni - 커맨드 처리 Delegate to CHARACTER class
//
ACMD(do_safebox_password)
{
@ -946,7 +946,7 @@ ACMD(do_mall_password)
return;
}
if (iPulse - ch->GetMallLoadTime() < passes_per_sec * 10) // 10초에 한번만 요청 가능
if (iPulse - ch->GetMallLoadTime() < passes_per_sec * 10) // 10초에 한번만 요청 가능
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC3\xA2\xB0\xED> \xC3\xA2\xB0\xED\xB8\xA6 \xB4\xDD\xC0\xBA\xC1\xF6 10\xC3\xCA \xBE\xC8\xBF\xA1\xB4\xC2 \xBF\xAD \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return;
@ -1028,20 +1028,20 @@ ACMD(do_set_run_mode)
ACMD(do_war)
{
//내 길드 정보를 얻어오고
//내 길드 정보를 얻어오고
CGuild * g = ch->GetGuild();
if (!g)
return;
//전쟁중인지 체크한번!
//전쟁중인지 체크한번!
if (g->UnderAnyWar())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xC0\xCC\xB9\xCC \xB4\xD9\xB8\xA5 \xC0\xFC\xC0\xEF\xBF\xA1 \xC2\xFC\xC0\xFC \xC1\xDF \xC0\xD4\xB4\xCF\xB4\xD9."));
return;
}
//파라메터를 두배로 나누고
//파라메터를 두배로 나누고
char arg1[256], arg2[256];
int type = GUILD_WAR_TYPE_FIELD;
two_arguments(argument, arg1, sizeof(arg1), arg2, sizeof(arg2));
@ -1057,17 +1057,17 @@ ACMD(do_war)
type = GUILD_WAR_TYPE_FIELD;
}
//길드의 마스터 아이디를 얻어온뒤
//길드의 마스터 아이디를 얻어온뒤
DWORD gm_pid = g->GetMasterPID();
//마스터인지 체크(길전은 길드장만이 가능)
//마스터인지 체크(길전은 길드장만이 가능)
if (gm_pid != ch->GetPlayerID())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB1\xE6\xB5\xE5\xC0\xFC\xBF\xA1 \xB4\xEB\xC7\xD1 \xB1\xC7\xC7\xD1\xC0\xCC \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return;
}
//상대 길드를 얻어오고
//상대 길드를 얻어오고
CGuild * opp_g = CGuildManager::instance().FindGuildByName(arg1);
if (!opp_g)
@ -1076,7 +1076,7 @@ ACMD(do_war)
return;
}
//상대길드와의 상태 체크
//상대길드와의 상태 체크
switch (g->GetGuildWarState(opp_g->GetID()))
{
case GUILD_WAR_NONE:
@ -1139,7 +1139,7 @@ ACMD(do_war)
if (!g->CanStartWar(type))
{
// 길드전을 할 수 있는 조건을 만족하지않는다.
// 길드전을 할 수 있는 조건을 만족하지않는다.
if (g->GetLadderPoint() == 0)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB7\xB9\xB4\xF5 \xC1\xA1\xBC\xF6\xB0\xA1 \xB8\xF0\xC0\xDA\xB6\xF3\xBC\xAD \xB1\xE6\xB5\xE5\xC0\xFC\xC0\xBB \xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
@ -1157,7 +1157,7 @@ ACMD(do_war)
return;
}
// 필드전 체크만 하고 세세한 체크는 상대방이 승낙할때 한다.
// 필드전 체크만 하고 세세한 체크는 상대방이 승낙할때 한다.
if (!opp_g->CanStartWar(GUILD_WAR_TYPE_FIELD))
{
if (opp_g->GetLadderPoint() == 0)
@ -1452,17 +1452,17 @@ ACMD(do_monarch_warpto)
return;
}
//군주 쿨타임 검사
//군주 쿨타임 검사
if (!ch->IsMCOK(CHARACTER::MI_WARP))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%d \xC3\xCA\xB0\xA3 \xC4\xF0\xC5\xB8\xC0\xD3\xC0\xCC \xC0\xFB\xBF\xEB\xC1\xDF\xC0\xD4\xB4\xCF\xB4\xD9."), ch->GetMCLTime(CHARACTER::MI_WARP));
return;
}
//군주 몹 소환 비용
//군주 몹 소환 비용
const int WarpPrice = 10000;
//군주 국고 검사
//군주 국고 검사
if (!CMonarch::instance().IsMoneyOk(WarpPrice, ch->GetEmpire()))
{
int NationMoney = CMonarch::instance().GetMoney(ch->GetEmpire());
@ -1516,10 +1516,10 @@ ACMD(do_monarch_warpto)
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s \xBF\xA1\xB0\xD4\xB7\xCE \xC0\xCC\xB5\xBF\xC7\xD5\xB4\xCF\xB4\xD9"), arg1);
ch->WarpSet(pos.x, pos.y);
//군주 돈 삭감
//군주 돈 삭감
CMonarch::instance().SendtoDBDecMoney(WarpPrice, ch->GetEmpire(), ch);
//쿨타임 초기화
//쿨타임 초기화
ch->SetMC(CHARACTER::MI_WARP);
}
}
@ -1550,10 +1550,10 @@ ACMD(do_monarch_warpto)
ch->WarpSet(x, y);
ch->Stop();
//군주 돈 삭감
//군주 돈 삭감
CMonarch::instance().SendtoDBDecMoney(WarpPrice, ch->GetEmpire(), ch);
//쿨타임 초기화
//쿨타임 초기화
ch->SetMC(CHARACTER::MI_WARP);
}
@ -1577,17 +1577,17 @@ ACMD(do_monarch_transfer)
return;
}
//군주 쿨타임 검사
//군주 쿨타임 검사
if (!ch->IsMCOK(CHARACTER::MI_TRANSFER))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%d \xC3\xCA\xB0\xA3 \xC4\xF0\xC5\xB8\xC0\xD3\xC0\xCC \xC0\xFB\xBF\xEB\xC1\xDF\xC0\xD4\xB4\xCF\xB4\xD9."), ch->GetMCLTime(CHARACTER::MI_TRANSFER));
return;
}
//군주 워프 비용
//군주 워프 비용
const int WarpPrice = 10000;
//군주 국고 검사
//군주 국고 검사
if (!CMonarch::instance().IsMoneyOk(WarpPrice, ch->GetEmpire()))
{
int NationMoney = CMonarch::instance().GetMoney(ch->GetEmpire());
@ -1635,9 +1635,9 @@ ACMD(do_monarch_transfer)
P2P_MANAGER::instance().Send(&pgg, sizeof(TPacketGGTransfer));
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s \xB4\xD4\xC0\xBB \xBC\xD2\xC8\xAF\xC7\xCF\xBF\xB4\xBD\xC0\xB4\xCF\xB4\xD9."), arg1);
//군주 돈 삭감
//군주 돈 삭감
CMonarch::instance().SendtoDBDecMoney(WarpPrice, ch->GetEmpire(), ch);
//쿨타임 초기화
//쿨타임 초기화
ch->SetMC(CHARACTER::MI_TRANSFER);
}
else
@ -1674,9 +1674,9 @@ ACMD(do_monarch_transfer)
//tch->Show(ch->GetMapIndex(), ch->GetX(), ch->GetY(), ch->GetZ());
tch->WarpSet(ch->GetX(), ch->GetY(), ch->GetMapIndex());
//군주 돈 삭감
//군주 돈 삭감
CMonarch::instance().SendtoDBDecMoney(WarpPrice, ch->GetEmpire(), ch);
//쿨타임 초기화
//쿨타임 초기화
ch->SetMC(CHARACTER::MI_TRANSFER);
}
@ -1766,14 +1766,14 @@ ACMD(do_monarch_tax)
return;
}
// 군주 검사
// 군주 검사
if (!ch->IsMonarch())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB1\xBA\xC1\xD6\xB8\xB8\xC0\xCC \xBB\xE7\xBF\xEB\xC7\xD2\xBC\xF6 \xC0\xD6\xB4\xC2 \xB1\xE2\xB4\xC9\xC0\xD4\xB4\xCF\xB4\xD9"));
return;
}
// 세금설정
// 세금설정
int tax = 0;
str_to_number(tax, arg1);
@ -1782,10 +1782,10 @@ ACMD(do_monarch_tax)
quest::CQuestManager::instance().SetEventFlag("trade_tax", tax);
// 군주에게 메세지 하나
// 군주에게 메세지 하나
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xBC\xBC\xB1\xDD\xC0\xCC %d %\xB7\xCE \xBC\xB3\xC1\xA4\xB5\xC7\xBE\xFA\xBD\xC0\xB4\xCF\xB4\xD9"));
// 공지
// 공지
char szMsg[1024];
snprintf(szMsg, sizeof(szMsg), "\xB1\xBA\xC1\xD6\xC0\xC7 \xB8\xED\xC0\xB8\xB7\xCE \xBC\xBC\xB1\xDD\xC0\xCC %d %% \xB7\xCE \xBA\xAF\xB0\xE6\xB5\xC7\xBE\xFA\xBD\xC0\xB4\xCF\xB4\xD9", tax);
@ -1794,32 +1794,32 @@ ACMD(do_monarch_tax)
snprintf(szMsg, sizeof(szMsg), "\xBE\xD5\xC0\xB8\xB7\xCE\xB4\xC2 \xB0\xC5\xB7\xA1 \xB1\xDD\xBE\xD7\xC0\xC7 %d %% \xB0\xA1 \xB1\xB9\xB0\xED\xB7\xCE \xB5\xE9\xBE\xEE\xB0\xA1\xB0\xD4\xB5\xCB\xB4\xCF\xB4\xD9.", tax);
BroadcastNotice(szMsg);
// 쿨타임 초기화
// 쿨타임 초기화
ch->SetMC(CHARACTER::MI_TAX);
}
static const DWORD cs_dwMonarchMobVnums[] =
{
191, // 산견신
192, // 저신
193, // 웅신
194, // 호신
391, // 미정
392, // 은정
393, // 세랑
394, // 진희
491, // 맹환
492, // 보우
493, // 구패
494, // 추흔
591, // 비류단대장
691, // 웅귀 족장
791, // 밀교교주
1304, // 누렁범귀
1901, // 구미호
2091, // 여왕거미
2191, // 거대사막거북
2206, // 화염왕i
191, // 산견신
192, // 저신
193, // 웅신
194, // 호신
391, // 미정
392, // 은정
393, // 세랑
394, // 진희
491, // 맹환
492, // 보우
493, // 구패
494, // 추흔
591, // 비류단대장
691, // 웅귀 족장
791, // 밀교교주
1304, // 누렁범귀
1901, // 구미호
2091, // 여왕거미
2191, // 거대사막거북
2206, // 화염왕i
0,
};
@ -1854,17 +1854,17 @@ ACMD(do_monarch_mob)
}
}
// 군주 몹 소환 비용
// 군주 몹 소환 비용
const int SummonPrice = 5000000;
// 군주 쿨타임 검사
// 군주 쿨타임 검사
if (!ch->IsMCOK(CHARACTER::MI_SUMMON))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%d \xC3\xCA\xB0\xA3 \xC4\xF0\xC5\xB8\xC0\xD3\xC0\xCC \xC0\xFB\xBF\xEB\xC1\xDF\xC0\xD4\xB4\xCF\xB4\xD9."), ch->GetMCLTime(CHARACTER::MI_SUMMON));
return;
}
// 군주 국고 검사
// 군주 국고 검사
if (!CMonarch::instance().IsMoneyOk(SummonPrice, ch->GetEmpire()))
{
int NationMoney = CMonarch::instance().GetMoney(ch->GetEmpire());
@ -1892,7 +1892,7 @@ ACMD(do_monarch_mob)
DWORD count;
// 소환 가능 몹 검사
// 소환 가능 몹 검사
for (count = 0; cs_dwMonarchMobVnums[count] != 0; ++count)
if (cs_dwMonarchMobVnums[count] == vnum)
break;
@ -1915,10 +1915,10 @@ ACMD(do_monarch_mob)
if (tch)
{
// 군주 돈 삭감
// 군주 돈 삭감
CMonarch::instance().SendtoDBDecMoney(SummonPrice, ch->GetEmpire(), ch);
// 쿨타임 초기화
// 쿨타임 초기화
ch->SetMC(CHARACTER::MI_SUMMON);
}
}
@ -2185,11 +2185,11 @@ ACMD(do_cube)
const std::string& strArg1 = std::string(arg1);
// r_info (request information)
// /cube r_info ==> (Client -> Server) 현재 NPC가 만들 수 있는 레시피 요청
// /cube r_info ==> (Client -> Server) 현재 NPC가 만들 수 있는 레시피 요청
// (Server -> Client) /cube r_list npcVNUM resultCOUNT 123,1/125,1/128,1/130,5
//
// /cube r_info 3 ==> (Client -> Server) 현재 NPC가 만들수 있는 레시피 중 3번째 아이템을 만드는 데 필요한 정보를 요청
// /cube r_info 3 5 ==> (Client -> Server) 현재 NPC가 만들수 있는 레시피 중 3번째 아이템부터 이후 5개의 아이템을 만드는 데 필요한 재료 정보를 요청
// /cube r_info 3 ==> (Client -> Server) 현재 NPC가 만들수 있는 레시피 중 3번째 아이템을 만드는 데 필요한 정보를 요청
// /cube r_info 3 5 ==> (Client -> Server) 현재 NPC가 만들수 있는 레시피 중 3번째 아이템부터 이후 5개의 아이템을 만드는 데 필요한 재료 정보를 요청
// (Server -> Client) /cube m_info startIndex count 125,1|126,2|127,2|123,5&555,5&555,4/120000@125,1|126,2|127,2|123,5&555,5&555,4/120000
//
if (strArg1 == "r_info")
@ -2278,7 +2278,7 @@ ACMD(do_in_game_mall)
return;
}
// ㅠ_ㅠ 쾌도서버 아이템몰 URL 하드코딩 추가
// ㅠ_ㅠ 쾌도서버 아이템몰 URL 하드코딩 추가
if (true == LC_IsWE_Korea())
{
ch->ChatPacket(CHAT_TYPE_COMMAND, "mall http://metin2.co.kr/50_we_mall/mall/login.htm");
@ -2354,7 +2354,7 @@ ACMD(do_in_game_mall)
}
}
// 주사위
// 주사위
ACMD(do_dice)
{
char arg1[256], arg2[256];
@ -2395,7 +2395,7 @@ ACMD(do_ride)
if (ch->IsDead() || ch->IsStun())
return;
// 내리기
// 내리기
{
if (ch->IsHorseRiding())
{
@ -2412,7 +2412,7 @@ ACMD(do_ride)
}
}
// 타기
// 타기
{
if (ch->GetHorse() != NULL)
{
@ -2427,7 +2427,7 @@ ACMD(do_ride)
if (NULL == item)
continue;
// 유니크 탈것 아이템
// 유니크 탈것 아이템
if (item->IsRideItem())
{
if (NULL==ch->GetWear(WEAR_UNIQUE1) || NULL==ch->GetWear(WEAR_UNIQUE2))
@ -2439,20 +2439,20 @@ ACMD(do_ride)
}
}
// 일반 탈것 아이템
// TODO : 탈것용 SubType 추가
// 일반 탈것 아이템
// TODO : 탈것용 SubType 추가
switch (item->GetVnum())
{
case 71114: // 저신이용권
case 71116: // 산견신이용권
case 71118: // 투지범이용권
case 71120: // 사자왕이용권
case 71114: // 저신이용권
case 71116: // 산견신이용권
case 71118: // 투지범이용권
case 71120: // 사자왕이용권
SPDLOG_TRACE("[DO_RIDE] USE QUEST ITEM");
ch->UseItem(TItemPos (INVENTORY, i));
return;
}
// GF mantis #113524, 52001~52090 번 탈것
// GF mantis #113524, 52001~52090 번 탈것
if( (item->GetVnum() > 52000) && (item->GetVnum() < 52091) ) {
SPDLOG_TRACE("[DO_RIDE] USE QUEST ITEM");
ch->UseItem(TItemPos (INVENTORY, i));
@ -2462,7 +2462,7 @@ ACMD(do_ride)
}
// 타거나 내릴 수 없을때
// 타거나 내릴 수 없을때
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB8\xBB\xC0\xBB \xB8\xD5\xC0\xFA \xBC\xD2\xC8\xAF\xC7\xD8\xC1\xD6\xBC\xBC\xBF\xE4."));
}
@ -2533,7 +2533,7 @@ ACMD(do_enroll_sale)
}
// temp_auction
// packet으로 통신하게 하고, 이건 삭제해야한다.
// packet으로 통신하게 하고, 이건 삭제해야한다.
ACMD(do_get_auction_list)
{
char arg1[256];

View File

@ -337,12 +337,12 @@ bool CHARACTER_GoToName(LPCHARACTER ch, BYTE empire, int mapIndex, const char* g
{ "Three|\xBD\xC2\xB7\xE6\xB0\xEE", 2, 64, 2704, 7399 },
{ "Three|\xBD\xC2\xB7\xE6\xB0\xEE", 3, 64, 3213, 8080 },
// 밀교사원
// 밀교사원
{ "Milgyo|\xB9\xD0\xB1\xB3\xBB\xE7\xBF\xF8", 1, 65, 5536, 1436 },
{ "Milgyo|\xB9\xD0\xB1\xB3\xBB\xE7\xBF\xF8", 2, 65, 5536, 1436 },
{ "Milgyo|\xB9\xD0\xB1\xB3\xBB\xE7\xBF\xF8", 3, 65, 5536, 1436 },
// 사귀타워입구
// 사귀타워입구
{ "\xBB\xE7\xB1\xCD\xC5\xB8\xBF\xF6\xC0\xD4\xB1\xB8", 1, 65, 5905, 1108 },
{ "\xBB\xE7\xB1\xCD\xC5\xB8\xBF\xF6\xC0\xD4\xB1\xB8", 2, 65, 5905, 1108 },
{ "\xBB\xE7\xB1\xCD\xC5\xB8\xBF\xF6\xC0\xD4\xB1\xB8", 3, 65, 5905, 1108 },
@ -888,7 +888,7 @@ struct FuncPurge
int iDist = DISTANCE_APPROX(pkChr->GetX() - m_pkGM->GetX(), pkChr->GetY() - m_pkGM->GetY());
if (!m_bAll && iDist >= 1000) // 10미터 이상에 있는 것들은 purge 하지 않는다.
if (!m_bAll && iDist >= 1000) // 10미터 이상에 있는 것들은 purge 하지 않는다.
return;
SPDLOG_DEBUG("PURGE: {} {}", pkChr->GetName(), iDist);
@ -1812,7 +1812,7 @@ LPCHARACTER chHori, chForge, chLib, chTemple, chTraining, chTree, chPortal, chBa
ACMD(do_b1)
{
//호리병 478 579
//호리병 478 579
chHori = CHARACTER_MANAGER::instance().SpawnMobRange(14017, ch->GetMapIndex(), 304222, 742858, 304222, 742858, true, false);
chHori->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_BUILDING_CONSTRUCTION_SMALL, 65535, 0, true);
chHori->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_DUNGEON_UNIQUE, 65535, 0, true);
@ -1859,25 +1859,25 @@ ACMD(do_b2)
ACMD(do_b3)
{
// 포지 492 547
// 포지 492 547
chForge = CHARACTER_MANAGER::instance().SpawnMobRange(14003, ch->GetMapIndex(), 307500, 746300, 307500, 746300, true, false);
chForge->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_DUNGEON_UNIQUE, 65535, 0, true);
//높은탑 509 589 -> 도서관
//높은탑 509 589 -> 도서관
chLib = CHARACTER_MANAGER::instance().SpawnMobRange(14007, ch->GetMapIndex(), 307900, 744500, 307900, 744500, true, false);
chLib->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_DUNGEON_UNIQUE, 65535, 0, true);
//욕조 513 606 -> 힘의신전
//욕조 513 606 -> 힘의신전
chTemple = CHARACTER_MANAGER::instance().SpawnMobRange(14004, ch->GetMapIndex(), 307700, 741600, 307700, 741600, true, false);
chTemple->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_DUNGEON_UNIQUE, 65535, 0, true);
//권투장 490 625
//권투장 490 625
chTraining= CHARACTER_MANAGER::instance().SpawnMobRange(14010, ch->GetMapIndex(), 307100, 739500, 307100, 739500, true, false);
chTraining->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_DUNGEON_UNIQUE, 65535, 0, true);
//나무 466 614
//나무 466 614
chTree= CHARACTER_MANAGER::instance().SpawnMobRange(14013, ch->GetMapIndex(), 300800, 741600, 300800, 741600, true, false);
chTree->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_DUNGEON_UNIQUE, 65535, 0, true);
//포탈 439 615
//포탈 439 615
chPortal= CHARACTER_MANAGER::instance().SpawnMobRange(14001, ch->GetMapIndex(), 300900, 744500, 300900, 744500, true, false);
chPortal->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_DUNGEON_UNIQUE, 65535, 0, true);
// 구슬 436 600
// 구슬 436 600
chBall = CHARACTER_MANAGER::instance().SpawnMobRange(14012, ch->GetMapIndex(), 302500, 746600, 302500, 746600, true, false);
chBall->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_DUNGEON_UNIQUE, 65535, 0, true);
}
@ -2121,7 +2121,7 @@ ACMD(do_reload)
break;
//END_RELOAD_ADMIN
case 'c': // cube
// 로컬 프로세스만 갱산한다.
// 로컬 프로세스만 갱산한다.
Cube_init ();
break;
}
@ -2245,7 +2245,7 @@ struct FuncWeaken
int iDist = DISTANCE_APPROX(pkChr->GetX() - m_pkGM->GetX(), pkChr->GetY() - m_pkGM->GetY());
if (!m_bAll && iDist >= 1000) // 10미터 이상에 있는 것들은 purge 하지 않는다.
if (!m_bAll && iDist >= 1000) // 10미터 이상에 있는 것들은 purge 하지 않는다.
return;
if (pkChr->IsNPC())
@ -2527,7 +2527,7 @@ ACMD(do_priv_empire)
if (duration < 0)
goto USAGE;
// 시간 단위로 변경
// 시간 단위로 변경
duration = duration * (60*60);
SPDLOG_DEBUG("_give_empire_privileage(empire={}, type={}, value={}, duration={}) by command",
@ -2631,7 +2631,7 @@ ACMD(do_xmas)
// BLOCK_CHAT
ACMD(do_block_chat_list)
{
// GM이 아니거나 block_chat_privilege가 없는 사람은 명령어 사용 불가
// GM이 아니거나 block_chat_privilege가 없는 사람은 명령어 사용 불가
if (!ch || (ch->GetGMLevel() < GM_HIGH_WIZARD && ch->GetQuestFlag("chat_privilege.block") <= 0))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB1\xD7\xB7\xB1 \xB8\xED\xB7\xC9\xBE\xEE\xB4\xC2 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9"));
@ -2697,7 +2697,7 @@ ACMD(do_vote_block_chat)
ACMD(do_block_chat)
{
// GM이 아니거나 block_chat_privilege가 없는 사람은 명령어 사용 불가
// GM이 아니거나 block_chat_privilege가 없는 사람은 명령어 사용 불가
if (ch && (ch->GetGMLevel() < GM_HIGH_WIZARD && ch->GetQuestFlag("chat_privilege.block") <= 0))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB1\xD7\xB7\xB1 \xB8\xED\xB7\xC9\xBE\xEE\xB4\xC2 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9"));
@ -2776,8 +2776,8 @@ ACMD(do_build)
CLand * pkLand = CManager::instance().FindLand(ch->GetMapIndex(), ch->GetX(), ch->GetY());
// NOTE: 조건 체크들은 클라이언트와 서버가 함께 하기 때문에 문제가 있을 때는
// 메세지를 전송하지 않고 에러를 출력한다.
// NOTE: 조건 체크들은 클라이언트와 서버가 함께 하기 때문에 문제가 있을 때는
// 메세지를 전송하지 않고 에러를 출력한다.
if (!pkLand)
{
SPDLOG_ERROR("{} trying to build on not buildable area.", ch->GetName());
@ -2790,17 +2790,17 @@ ACMD(do_build)
return;
}
// 건설 권한 체크
// 건설 권한 체크
if (GMLevel == GM_PLAYER)
{
// 플레이어가 집을 지을 때는 땅이 내껀지 확인해야 한다.
// 플레이어가 집을 지을 때는 땅이 내껀지 확인해야 한다.
if ((!ch->GetGuild() || ch->GetGuild()->GetID() != pkLand->GetOwner()))
{
SPDLOG_ERROR("{} trying to build on not owned land.", ch->GetName());
return;
}
// 내가 길마인가?
// 내가 길마인가?
if (ch->GetGuild()->GetMasterPID() != ch->GetPlayerID())
{
SPDLOG_ERROR("{} trying to build while not the guild master.", ch->GetName());
@ -2846,13 +2846,13 @@ ACMD(do_build)
}
}
// 건물 종속성 체크 (이 건물이 지어져 있어야함)
// 건물 종속성 체크 (이 건물이 지어져 있어야함)
if (t->dwDependOnGroupVnum)
{
// const TObjectProto * dependent = CManager::instance().GetObjectProto(dwVnum);
// if (dependent)
{
// 지어져있는가?
// 지어져있는가?
if (!pkLand->FindObjectByGroup(t->dwDependOnGroupVnum))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB0\xC7\xBC\xB3\xBF\xA1 \xC7\xCA\xBF\xE4\xC7\xD1 \xB0\xC7\xB9\xB0\xC0\xCC \xC1\xF6\xBE\xEE\xC1\xAE \xC0\xD6\xC1\xF6 \xBE\xCA\xBD\xC0\xB4\xCF\xB4\xD9."));
@ -2863,8 +2863,8 @@ ACMD(do_build)
if (test_server || GMLevel == GM_PLAYER)
{
// GM이 아닐경우만 (테섭에서는 GM도 소모)
// 건설 비용 체크
// GM이 아닐경우만 (테섭에서는 GM도 소모)
// 건설 비용 체크
if (t->dwPrice > BUILDING_MAX_PRICE)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB0\xC7\xB9\xB0 \xBA\xF1\xBF\xEB \xC1\xA4\xBA\xB8 \xC0\xCC\xBB\xF3\xC0\xB8\xB7\xCE \xB0\xC7\xBC\xB3 \xC0\xDB\xBE\xF7\xBF\xA1 \xBD\xC7\xC6\xD0\xC7\xDF\xBD\xC0\xB4\xCF\xB4\xD9."));
@ -2877,7 +2877,7 @@ ACMD(do_build)
return;
}
// 아이템 자재 개수 체크
// 아이템 자재 개수 체크
int i;
for (i = 0; i < OBJECT_MATERIAL_MAX_NUM; ++i)
@ -2899,7 +2899,7 @@ ACMD(do_build)
float x_rot = atof(arg4);
float y_rot = atof(arg5);
float z_rot = atof(arg6);
// 20050811.myevan.건물 회전 기능 봉인 해제
// 20050811.myevan.건물 회전 기능 봉인 해제
/*
if (x_rot != 0.0f || y_rot != 0.0f || z_rot != 0.0f)
{
@ -2929,12 +2929,12 @@ ACMD(do_build)
}
if (test_server || GMLevel == GM_PLAYER)
// 건설 재료 소모하기 (테섭에서는 GM도 소모)
// 건설 재료 소모하기 (테섭에서는 GM도 소모)
{
// 건설 비용 소모
// 건설 비용 소모
ch->PointChange(POINT_GOLD, -t->dwPrice);
// 아이템 자재 사용하기
// 아이템 자재 사용하기
{
int i;
for (i = 0; i < OBJECT_MATERIAL_MAX_NUM; ++i)
@ -3013,8 +3013,8 @@ ACMD(do_build)
break;
case 'W' :
// 담장 세우기
// build (w)all 담장번호 담장크기 대문동 대문서 대문남 대문북
// 담장 세우기
// build (w)all 담장번호 담장크기 대문동 대문서 대문남 대문북
if (GMLevel > GM_PLAYER)
{
@ -3048,8 +3048,8 @@ ACMD(do_build)
break;
case 'E' :
// 담장 지우기
// build (e)rase 담장셋ID
// 담장 지우기
// build (e)rase 담장셋ID
if (GMLevel > GM_PLAYER)
{
one_argument(line, arg1, sizeof(arg1));
@ -3323,7 +3323,7 @@ ACMD(do_duel)
if (!str_to_number(minute, szMinute))
{
// 캐나다는 기본 10분.
// 캐나다는 기본 10분.
if (LC_IsCanada() == true)
{
minute = 10;
@ -3430,28 +3430,28 @@ ACMD(do_stat_plus_amount)
switch (subcmd)
{
case POINT_HT : // 체력
case POINT_HT : // 체력
if (nPoint + ch->GetPoint(POINT_HT) > 90)
{
nPoint = 90 - ch->GetPoint(POINT_HT);
}
break;
case POINT_IQ : // 지능
case POINT_IQ : // 지능
if (nPoint + ch->GetPoint(POINT_IQ) > 90)
{
nPoint = 90 - ch->GetPoint(POINT_IQ);
}
break;
case POINT_ST : // 근력
case POINT_ST : // 근력
if (nPoint + ch->GetPoint(POINT_ST) > 90)
{
nPoint = 90 - ch->GetPoint(POINT_ST);
}
break;
case POINT_DX : // 민첩
case POINT_DX : // 민첩
if (nPoint + ch->GetPoint(POINT_DX) > 90)
{
nPoint = 90 - ch->GetPoint(POINT_DX);
@ -4208,8 +4208,8 @@ ACMD (do_attr_full_set)
case JOB_SURA:
case JOB_SHAMAN:
{
// 무사 몸빵 셋팅.
// 이것만 나와 있어서 임시로 모든 직군 다 이런 속성 따름.
// 무사 몸빵 셋팅.
// 이것만 나와 있어서 임시로 모든 직군 다 이런 속성 따름.
item = ch->GetWear(WEAR_HEAD);
if (item != NULL)
{

View File

@ -102,17 +102,17 @@ int SPEEDHACK_LIMIT_COUNT = 50;
int SPEEDHACK_LIMIT_BONUS = 80;
int g_iSyncHackLimitCount = 20; // 10 -> 20 2013 09 11 CYH
//<EFBFBD>þ<EFBFBD> = VIEW_RANGE + VIEW_BONUS_RANGE
//VIEW_BONUSE_RANGE : Ŭ<EFBFBD><EFBFBD><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><EFBFBD> <20>þ<EFBFBD> ó<><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߻<EFBFBD><DFBB>Ҽ<EFBFBD><D2BC>־<EFBFBD> 500CM<43><4D> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>׻<EFBFBD><D7BB>ش<EFBFBD>.
//시야 = VIEW_RANGE + VIEW_BONUS_RANGE
//VIEW_BONUSE_RANGE : 클라이언트와 시야 처리에서너무 딱 떨어질경우 문제가 발생할수있어 500CM의 여분을 항상준다.
int VIEW_RANGE = 5000;
int VIEW_BONUS_RANGE = 500;
int g_server_id = 0;
string g_strWebMallURL = "www.metin2.de";
unsigned int g_uiSpamBlockDuration = 60 * 15; // <EFBFBD>⺻ 15<31><35>
unsigned int g_uiSpamBlockScore = 100; // <EFBFBD>⺻ 100<30><30>
unsigned int g_uiSpamReloadCycle = 60 * 10; // <EFBFBD>⺻ 10<31><30>
unsigned int g_uiSpamBlockDuration = 60 * 15; // 기본 15분
unsigned int g_uiSpamBlockScore = 100; // 기본 100점
unsigned int g_uiSpamReloadCycle = 60 * 10; // 기본 10분
bool g_bCheckMultiHack = true;
@ -121,8 +121,8 @@ int g_iSpamBlockMaxLevel = 10;
void LoadStateUserCount();
void LoadValidCRCList();
bool LoadClientVersion();
bool g_protectNormalPlayer = false; // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڰ<EFBFBD> "<22><>ȭ<EFBFBD><C8AD><EFBFBD>" <20><> <20>Ϲ<EFBFBD><CFB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
bool g_noticeBattleZone = false; // <EFBFBD>߸<EFBFBD><EFBFBD><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD> <20>ȳ<EFBFBD><C8B3>޼<EFBFBD><DEBC><EFBFBD><EFBFBD><EFBFBD> <20>˷<EFBFBD><CBB7><EFBFBD>
bool g_protectNormalPlayer = false; // 범법자가 "평화모드" 인 일반유저를 공격하지 못함
bool g_noticeBattleZone = false; // 중립지대에 입장하면 안내메세지를 알려줌
int gPlayerMaxLevel = 99;
@ -318,7 +318,7 @@ void config_init(const string& st_localeServiceName)
}
char db_host[2][64], db_user[2][64], db_pwd[2][64], db_db[2][64];
// ... <EFBFBD><EFBFBD>... db_port<72><74> <20>̹<EFBFBD> <20>ִµ<D6B4>... <20><><EFBFBD>̹<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD><D8BE><EFBFBD>...
// ... 아... db_port는 이미 있는데... 네이밍 어찌해야함...
int mysql_db_port[2];
for (int n = 0; n < 2; ++n)
@ -339,9 +339,9 @@ void config_init(const string& st_localeServiceName)
*log_db = '\0';
// DB<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD><CFB1><EFBFBD><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD> <20>ٸ<EFBFBD> <20><><EFBFBD>ð<EFBFBD><C3B0><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ǿ
// DB<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>о<EFBFBD><D0BE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ٸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE>Ѵ<EFBFBD>.
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD><CFB0>õ<EFBFBD> <20>ʱ<EFBFBD>ȭ <20><>ƾ<EFBFBD><C6BE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD>.
// DB에서 로케일정보를 세팅하기위해서는 다른 세팅값보다 선행되어서
// DB정보만 읽어와 로케일 세팅을 한후 다른 세팅을 적용시켜야한다.
// 이유는 로케일관련된 초기화 루틴이 곳곳에 존재하기 때문.
bool isCommonSQL = false;
bool isPlayerSQL = false;
@ -477,7 +477,7 @@ void config_init(const string& st_localeServiceName)
}
}
//ó<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
//처리가 끝났으니 파일을 닫자.
fclose(fpOnlyForDB);
// CONFIG_SQL_INFO_ERROR
@ -503,7 +503,7 @@ void config_init(const string& st_localeServiceName)
exit(EXIT_FAILURE);
}
// Common DB <EFBFBD><EFBFBD> Locale <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD> <20>Ѵ<EFBFBD>.
// Common DB 가 Locale 정보를 가지고 있기 때문에 가장 먼저 접속해야 한다.
AccountDB::instance().Connect(db_host[1], mysql_db_port[1], db_user[1], db_pwd[1], db_db[1]);
if (false == AccountDB::instance().IsConnected())
@ -514,8 +514,8 @@ void config_init(const string& st_localeServiceName)
SPDLOG_INFO("CommonSQL connected");
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <<EFBFBD><EFBFBD><EFBFBD>> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ǹ<EFBFBD>(WHERE) <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. (<28>ٸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20>ֽ<EFBFBD><D6BD>ϴ<EFBFBD>)
// 로케일 정보를 가져오자
// <경고> 쿼리문에 절대 조건문(WHERE) 달지 마세요. (다른 지역에서 문제가 생길수 있습니다)
{
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "SELECT mKey, mValue FROM locale");
@ -532,7 +532,7 @@ void config_init(const string& st_localeServiceName)
while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
{
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// 로케일 세팅
if (strcasecmp(row[0], "LOCALE") == 0)
{
if (LocaleService_Init(row[1]) == false)
@ -544,15 +544,15 @@ void config_init(const string& st_localeServiceName)
}
}
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> COMMON SQL<51><4C> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> g_stLocale <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> LocaleService_Init() <20><><EFBFBD>ο<EFBFBD><CEBF><EFBFBD> <20><><EFBFBD>õȴ<C3B5>.
// 로케일 정보를 COMMON SQL에 세팅해준다.
// 참고로 g_stLocale 정보는 LocaleService_Init() 내부에서 세팅된다.
SPDLOG_INFO("Setting DB to locale {}", g_stLocale.c_str());
AccountDB::instance().SetLocale(g_stLocale);
AccountDB::instance().ConnectAsync(db_host[1], mysql_db_port[1], db_user[1], db_pwd[1], db_db[1], g_stLocale.c_str());
// Player DB <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Player DB 접속
DBManager::instance().Connect(db_host[0], mysql_db_port[0], db_user[0], db_pwd[0], db_db[0]);
if (!DBManager::instance().IsConnected())
@ -563,9 +563,9 @@ void config_init(const string& st_localeServiceName)
SPDLOG_INFO("PlayerSQL connected");
if (false == g_bAuthServer) // <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ƴ<EFBFBD> <20><><EFBFBD>
if (false == g_bAuthServer) // 인증 서버가 아닐 경우
{
// Log DB <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Log DB 접속
LogManager::instance().Connect(log_host, log_port, log_user, log_pwd, log_db);
if (!LogManager::instance().IsConnected())
@ -580,8 +580,8 @@ void config_init(const string& st_localeServiceName)
}
// SKILL_POWER_BY_LEVEL
// <EFBFBD><EFBFBD>Ʈ<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ؼ<EFBFBD> AccountDB::instance().SetLocale(g_stLocale) <20>ĺ<EFBFBD><C4BA><EFBFBD> <20>Ѵ<EFBFBD>.
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ȵȴ<C8B5>(<28>ؿܰ<D8BF> <20><><EFBFBD><EFBFBD>)
// 스트링 비교의 문제로 인해서 AccountDB::instance().SetLocale(g_stLocale) 후부터 한다.
// 물론 국내는 별로 문제가 안된다(해외가 문제)
{
char szQuery[256];
snprintf(szQuery, sizeof(szQuery), "SELECT mValue FROM locale WHERE mKey='SKILL_POWER_BY_LEVEL'");
@ -621,13 +621,13 @@ void config_init(const string& st_localeServiceName)
}
}
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ų <20><><EFBFBD><EFBFBD>
// 종족별 스킬 세팅
for (int job = 0; job < JOB_MAX_NUM * 2; ++job)
{
snprintf(szQuery, sizeof(szQuery), "SELECT mValue from locale where mKey='SKILL_POWER_BY_LEVEL_TYPE%d' ORDER BY CAST(mValue AS unsigned)", job);
std::unique_ptr<SQLMsg> pMsg(AccountDB::instance().DirectQuery(szQuery));
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ȵǾ<C8B5><C7BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD><E2BABB><EFBFBD>̺<EFBFBD><CCBA><EFBFBD> <20><><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
// 세팅이 안되어있으면 기본테이블을 사용한다.
if (pMsg->Get()->uiNumRows == 0)
{
CTableBySkill::instance().SetSkillPowerByLevelFromType(job, aiBaseSkillPowerByLevelTable);
@ -1002,7 +1002,7 @@ void config_init(const string& st_localeServiceName)
TOKEN("spam_block_reload_cycle")
{
str_to_number(g_uiSpamReloadCycle, value_string);
g_uiSpamReloadCycle = std::max<int>(60, g_uiSpamReloadCycle); // <EFBFBD>ּ<EFBFBD> 1<><31>
g_uiSpamReloadCycle = std::max<int>(60, g_uiSpamReloadCycle); // 최소 1분
}
TOKEN("check_multihack")

View File

@ -14,7 +14,7 @@ TJobInitialPoints JobInitialPoints[JOB_MAX_NUM] =
}
*/
{
// str con dex int 초기HP 초기SP CON/HP INT/SP HP랜덤/lv MP랜덤/lv 초기stam stam/con stam/lv
// str con dex int 초기HP 초기SP CON/HP INT/SP HP랜덤/lv MP랜덤/lv 초기stam stam/con stam/lv
{ 6, 4, 3, 3, 600, 200, 40, 20, 36, 44, 18, 22, 800, 5, 1, 3 }, // JOB_WARRIOR 16
{ 4, 3, 6, 3, 650, 200, 40, 20, 36, 44, 18, 22, 800, 5, 1, 3 }, // JOB_ASSASSIN 16
{ 5, 3, 3, 5, 650, 200, 40, 20, 36, 44, 18, 22, 800, 5, 1, 3 }, // JOB_SURA 16
@ -162,7 +162,7 @@ const DWORD exp_table_euckr[PLAYER_EXP_TABLE_MAX + 1] =
1676898443,
1844588288,
2029047116,
2100000000, // 99 99레벨일 때 필요경험치 (100레벨이 되기 위한)
2100000000, // 99 99레벨일 때 필요경험치 (100레벨이 되기 위한)
2100000000, // 100
2100000000,
2100000000,
@ -287,7 +287,7 @@ const DWORD exp_table_common[PLAYER_EXP_TABLE_MAX + 1] =
1676898443,
1844588288,
2029047116,
2050000000, // 99레벨 일 때 필요경험치 (100레벨이 되기 위한)
2050000000, // 99레벨 일 때 필요경험치 (100레벨이 되기 위한)
2150000000, // 100
2210000000,
2250000000,
@ -412,7 +412,7 @@ const DWORD exp_table_newcibn[PLAYER_EXP_TABLE_MAX + 1 ] =
2000000000,
2000000000,
2000000000,
2000000000, // 99 99레벨일 때 필요경험치 (100레벨이 되기 위한).. 현재 CIBN이 어떻게 운영하고 있는 지 모르니 신규 테이블을 쓰지 않고 기존값 계속 연장 유지
2000000000, // 99 99레벨일 때 필요경험치 (100레벨이 되기 위한).. 현재 CIBN이 어떻게 운영하고 있는 지 모르니 신규 테이블을 쓰지 않고 기존값 계속 연장 유지
2000000000, // 100
2000000000,
2000000000,
@ -439,8 +439,8 @@ const DWORD exp_table_newcibn[PLAYER_EXP_TABLE_MAX + 1 ] =
const int * aiPercentByDeltaLev = NULL;
const int * aiPercentByDeltaLevForBoss = NULL;
// 적과 나와의 레벨차이에 의한 계산에 사용되는 테이블
// MIN(MAX_EXP_DELTA_OF_LEV - 1, (적렙 + 15) - 내렙))
// 적과 나와의 레벨차이에 의한 계산에 사용되는 테이블
// MIN(MAX_EXP_DELTA_OF_LEV - 1, (적렙 + 15) - 내렙))
const int aiPercentByDeltaLevForBoss_euckr[MAX_EXP_DELTA_OF_LEV] =
{
1, // -15 0
@ -720,7 +720,7 @@ const DWORD guild_exp_table[GUILD_MAX_LEVEL+1] =
42000000UL
};
// INTERNATIONAL_VERSION 길드경험치
// INTERNATIONAL_VERSION 길드경험치
const DWORD guild_exp_table2[GUILD_MAX_LEVEL+1] =
{
0,
@ -745,7 +745,7 @@ const DWORD guild_exp_table2[GUILD_MAX_LEVEL+1] =
4000000UL,
16800000UL
};
// END_OF_INTERNATIONAL_VERSION 길드경험치
// END_OF_INTERNATIONAL_VERSION 길드경험치
const int aiMobEnchantApplyIdx[MOB_ENCHANTS_MAX_NUM] =
{
@ -898,16 +898,16 @@ const TApplyInfo aApplyInfo[MAX_APPLY_NUM] =
{ POINT_PC_BANG_DROP_BONUS }, // 76
// END_PC_BANG_ITEM_ADD
{ POINT_NONE, }, // 77 사용시 HP 소모 APPLY_EXTRACT_HP_PCT
{ POINT_NONE, }, // 77 사용시 HP 소모 APPLY_EXTRACT_HP_PCT
{ POINT_RESIST_WARRIOR, }, // 78 무사에게 저항 APPLY_RESIST_WARRIOR
{ POINT_RESIST_ASSASSIN, }, // 79 자객에게 저항 APPLY_RESIST_ASSASSIN
{ POINT_RESIST_SURA, }, // 80 수라에게 저항 APPLY_RESIST_SURA
{ POINT_RESIST_SHAMAN, }, // 81 무당에게 저항 APPLY_RESIST_SHAMAN
{ POINT_ENERGY }, // 82 기력
{ POINT_DEF_GRADE }, // 83 방어력. DEF_GRADE_BONUS는 클라에서 두배로 보여지는 의도된 버그(...)가 있다.
{ POINT_COSTUME_ATTR_BONUS }, // 84 코스튬에 붙은 속성에 대해서만 보너스를 주는 기력
{ POINT_MAGIC_ATT_BONUS_PER }, // 85 마법 공격력 +x%
{ POINT_RESIST_WARRIOR, }, // 78 무사에게 저항 APPLY_RESIST_WARRIOR
{ POINT_RESIST_ASSASSIN, }, // 79 자객에게 저항 APPLY_RESIST_ASSASSIN
{ POINT_RESIST_SURA, }, // 80 수라에게 저항 APPLY_RESIST_SURA
{ POINT_RESIST_SHAMAN, }, // 81 무당에게 저항 APPLY_RESIST_SHAMAN
{ POINT_ENERGY }, // 82 기력
{ POINT_DEF_GRADE }, // 83 방어력. DEF_GRADE_BONUS는 클라에서 두배로 보여지는 의도된 버그(...)가 있다.
{ POINT_COSTUME_ATTR_BONUS }, // 84 코스튬에 붙은 속성에 대해서만 보너스를 주는 기력
{ POINT_MAGIC_ATT_BONUS_PER }, // 85 마법 공격력 +x%
{ POINT_MELEE_MAGIC_ATT_BONUS_PER }, // 86 APPLY_MELEE_MAGIC_ATTBONUS_PER
{ POINT_RESIST_ICE, }, // APPLY_RESIST_ICE, 87
{ POINT_RESIST_EARTH, }, // APPLY_RESIST_EARTH, 88
@ -1153,28 +1153,28 @@ TGuildWarInfo KOR_aGuildWarInfo[GUILD_WAR_TYPE_MAX_NUM] =
};
//
// 악세서리 소켓용 수치들
// 악세서리 소켓용 수치들
//
// 다이아몬드로 소켓을 추가할 때 확률
// 다이아몬드로 소켓을 추가할 때 확률
const int aiAccessorySocketAddPct[ITEM_ACCESSORY_SOCKET_MAX_NUM] =
{
50, 50, 50
};
// 악세서리 수치 값의 몇%만큼의 성능을 추가하는지
// 악세서리 수치 값의 몇%만큼의 성능을 추가하는지
const int aiAccessorySocketEffectivePct[ITEM_ACCESSORY_SOCKET_MAX_NUM + 1] =
{
0, 10, 20, 40
};
// 소켓 지속시간 24, 12, 6
// 소켓 지속시간 24, 12, 6
const int aiAccessorySocketDegradeTime[ITEM_ACCESSORY_SOCKET_MAX_NUM + 1] =
{
0, 3600 * 24, 3600 * 12, 3600 * 6
};
// 소켓 장착 성공률
// 소켓 장착 성공률
const int aiAccessorySocketPutPct[ITEM_ACCESSORY_SOCKET_MAX_NUM + 1] =
{
90, 80, 70, 0
@ -1274,10 +1274,10 @@ TValueName c_aApplyTypeNames[] =
{ "RESIST_ASSASSIN", APPLY_RESIST_ASSASSIN},
{ "RESIST_SURA", APPLY_RESIST_SURA},
{ "RESIST_SHAMAN", APPLY_RESIST_SHAMAN},
// by mhh game/affect.h 정의되어있음. INFINITE_AFFECT_DURATION = 0x1FFFFFFF
// by mhh game/affect.h 정의되어있음. INFINITE_AFFECT_DURATION = 0x1FFFFFFF
{ "INFINITE_AFFECT_DURATION", 0x1FFFFFFF },
{ "ENERGY", APPLY_ENERGY }, // 기력
{ "COSTUME_ATTR_BONUS", APPLY_COSTUME_ATTR_BONUS }, // 기력
{ "ENERGY", APPLY_ENERGY }, // 기력
{ "COSTUME_ATTR_BONUS", APPLY_COSTUME_ATTR_BONUS }, // 기력
{ "MAGIC_ATTBONUS_PER", APPLY_MAGIC_ATTBONUS_PER },
{ "MELEE_MAGIC_ATTBONUS_PER", APPLY_MELEE_MAGIC_ATTBONUS_PER },

View File

@ -37,11 +37,11 @@ static bool s_isInitializedCubeMaterialInformation = false;
/*--------------------------------------------------------*/
enum ECubeResultCategory
{
CUBE_CATEGORY_POTION, // 약초, 진액 등등.. (포션으로 특정할 수 없으니 사용 안 함. 약초같은건 다 걍 기타)
CUBE_CATEGORY_WEAPON, // 무기
CUBE_CATEGORY_ARMOR, // 방어구
CUBE_CATEGORY_ACCESSORY, // 장신구
CUBE_CATEGORY_ETC, // 기타 등등...
CUBE_CATEGORY_POTION, // 약초, 진액 등등.. (포션으로 특정할 수 없으니 사용 안 함. 약초같은건 다 걍 기타)
CUBE_CATEGORY_WEAPON, // 무기
CUBE_CATEGORY_ARMOR, // 방어구
CUBE_CATEGORY_ACCESSORY, // 장신구
CUBE_CATEGORY_ETC, // 기타 등등...
};
typedef std::vector<CUBE_VALUE> TCubeValueVector;
@ -53,12 +53,12 @@ struct SCubeMaterialInfo
bHaveComplicateMaterial = false;
};
CUBE_VALUE reward; // 보상이 뭐냐
TCubeValueVector material; // 재료들은 뭐냐
DWORD gold; // 돈은 얼마드냐
TCubeValueVector complicateMaterial; // 복잡한-_- 재료들
CUBE_VALUE reward; // 보상이 뭐냐
TCubeValueVector material; // 재료들은 뭐냐
DWORD gold; // 돈은 얼마드냐
TCubeValueVector complicateMaterial; // 복잡한-_- 재료들
// .. 클라이언트에서 재료를 보여주기 위하여 약속한 포맷
// .. 클라이언트에서 재료를 보여주기 위하여 약속한 포맷
// 72723,1&72724,2&72730,1
// 52001,1|52002,1|52003,1&72723,1&72724,5
// => ( 52001,1 or 52002,1 or 52003,1 ) and 72723,1 and 72724,5
@ -75,13 +75,13 @@ struct SItemNameAndLevel
};
// 자료구조나 이런거 병신인건 이해좀... 누구땜에 영혼이 없는 상태에서 만들었씀
// 자료구조나 이런거 병신인건 이해좀... 누구땜에 영혼이 없는 상태에서 만들었씀
typedef std::vector<SCubeMaterialInfo> TCubeResultList;
typedef std::unordered_map<DWORD, TCubeResultList> TCubeMapByNPC; // 각각의 NPC별로 어떤 걸 만들 수 있고 재료가 뭔지...
typedef std::unordered_map<DWORD, std::string> TCubeResultInfoTextByNPC; // 각각의 NPC별로 만들 수 있는 목록을 정해진 포맷으로 정리한 정보
typedef std::unordered_map<DWORD, TCubeResultList> TCubeMapByNPC; // 각각의 NPC별로 어떤 걸 만들 수 있고 재료가 뭔지...
typedef std::unordered_map<DWORD, std::string> TCubeResultInfoTextByNPC; // 각각의 NPC별로 만들 수 있는 목록을 정해진 포맷으로 정리한 정보
TCubeMapByNPC cube_info_map;
TCubeResultInfoTextByNPC cube_result_info_map_by_npc; // 네이밍 존나 병신같다 ㅋㅋㅋ
TCubeResultInfoTextByNPC cube_result_info_map_by_npc; // 네이밍 존나 병신같다 ㅋㅋㅋ
class CCubeMaterialInfoHelper
{
@ -92,7 +92,7 @@ public:
/*--------------------------------------------------------*/
/* STATIC FUNCTIONS */
/*--------------------------------------------------------*/
// 필요한 아이템 개수를 가지고있는가?
// 필요한 아이템 개수를 가지고있는가?
static bool FN_check_item_count (LPITEM *items, DWORD item_vnum, int need_count)
{
int count = 0;
@ -111,7 +111,7 @@ static bool FN_check_item_count (LPITEM *items, DWORD item_vnum, int need_count)
return (count>=need_count);
}
// 큐브내의 재료를 지운다.
// 큐브내의 재료를 지운다.
static void FN_remove_material (LPITEM *items, DWORD item_vnum, int need_count)
{
int count = 0;
@ -170,7 +170,7 @@ static bool FN_check_valid_npc( WORD vnum )
return false;
}
// 큐브데이타가 올바르게 초기화 되었는지 체크한다.
// 큐브데이타가 올바르게 초기화 되었는지 체크한다.
static bool FN_check_cube_data (CUBE_DATA *cube_data)
{
DWORD i = 0;
@ -204,10 +204,10 @@ CUBE_DATA::CUBE_DATA()
this->gold = 0;
}
// 필요한 재료의 수량을 만족하는지 체크한다.
// 필요한 재료의 수량을 만족하는지 체크한다.
bool CUBE_DATA::can_make_item (LPITEM *items, WORD npc_vnum)
{
// 필요한 재료, 수량을 만족하는지 체크한다.
// 필요한 재료, 수량을 만족하는지 체크한다.
DWORD i, end_index;
DWORD need_vnum;
int need_count;
@ -235,7 +235,7 @@ bool CUBE_DATA::can_make_item (LPITEM *items, WORD npc_vnum)
return true;
}
// 큐브를 돌렸을때 나오는 아이템의 종류를 결정함
// 큐브를 돌렸을때 나오는 아이템의 종류를 결정함
CUBE_VALUE* CUBE_DATA::reward_value ()
{
int end_index = 0;
@ -248,7 +248,7 @@ CUBE_VALUE* CUBE_DATA::reward_value ()
return &this->reward[reward_index];
}
// 큐브에 들어있는 재료를 지운다
// 큐브에 들어있는 재료를 지운다
void CUBE_DATA::remove_material (LPCHARACTER ch)
{
DWORD i, end_index;
@ -281,7 +281,7 @@ void Cube_clean_item (LPCHARACTER ch)
}
}
// 큐브창 열기
// 큐브창 열기
void Cube_open (LPCHARACTER ch)
{
if (false == s_isInitializedCubeMaterialInformation)
@ -331,7 +331,7 @@ void Cube_open (LPCHARACTER ch)
ch->ChatPacket(CHAT_TYPE_COMMAND, "cube open %d", npc->GetRaceNum());
}
// 큐브 캔슬
// 큐브 캔슬
void Cube_close (LPCHARACTER ch)
{
RETURN_IF_CUBE_IS_NOT_OPENED(ch);
@ -426,7 +426,7 @@ bool Cube_load (const char *file)
}
else TOKEN("gold")
{
// 제조에 필요한 금액
// 제조에 필요한 금액
cube_data->gold = value1;
}
else TOKEN("end")
@ -504,10 +504,10 @@ static bool FN_update_cube_status(LPCHARACTER ch)
// return new item
bool Cube_make (LPCHARACTER ch)
{
// 주어진 아이템을 필요로하는 조합을 찾는다. (큐브데이타로 칭함)
// 큐브 데이타가 있다면 아이템의 재료를 체크한다.
// 새로운 아이템을 만든다.
// 새로운 아이템 지급
// 주어진 아이템을 필요로하는 조합을 찾는다. (큐브데이타로 칭함)
// 큐브 데이타가 있다면 아이템의 재료를 체크한다.
// 새로운 아이템을 만든다.
// 새로운 아이템 지급
LPCHARACTER npc;
int percent_number = 0;
@ -538,23 +538,23 @@ bool Cube_make (LPCHARACTER ch)
if (ch->GetGold() < cube_proto->gold)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB5\xB7\xC0\xCC \xBA\xCE\xC1\xB7\xC7\xCF\xB0\xC5\xB3\xAA \xBE\xC6\xC0\xCC\xC5\xDB\xC0\xCC \xC1\xA6\xC0\xDA\xB8\xAE\xBF\xA1 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9.")); // 이 텍스트는 이미 널리 쓰이는거라 추가번역 필요 없음
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB5\xB7\xC0\xCC \xBA\xCE\xC1\xB7\xC7\xCF\xB0\xC5\xB3\xAA \xBE\xC6\xC0\xCC\xC5\xDB\xC0\xCC \xC1\xA6\xC0\xDA\xB8\xAE\xBF\xA1 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9.")); // 이 텍스트는 이미 널리 쓰이는거라 추가번역 필요 없음
return false;
}
CUBE_VALUE *reward_value = cube_proto->reward_value();
// 사용되었던 재료아이템 삭제
// 사용되었던 재료아이템 삭제
cube_proto->remove_material (ch);
// 제조시 필요한 골드 차감
// 제조시 필요한 골드 차감
if (0 < cube_proto->gold)
ch->PointChange(POINT_GOLD, -(cube_proto->gold), false);
percent_number = Random::get(1,100);
if ( percent_number<=cube_proto->percent)
{
// 성공
// 성공
ch->ChatPacket(CHAT_TYPE_COMMAND, "cube success %d %d", reward_value->vnum, reward_value->count);
new_item = ch->AutoGiveItem(reward_value->vnum, reward_value->count);
@ -564,8 +564,8 @@ bool Cube_make (LPCHARACTER ch)
}
else
{
// 실패
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xC1\xA6\xC1\xB6\xBF\xA1 \xBD\xC7\xC6\xD0\xC7\xCF\xBF\xB4\xBD\xC0\xB4\xCF\xB4\xD9.")); // 2012.11.12 새로 추가된 메세지 (locale_string.txt 에 추가해야 함)
// 실패
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xC1\xA6\xC1\xB6\xBF\xA1 \xBD\xC7\xC6\xD0\xC7\xCF\xBF\xB4\xBD\xC0\xB4\xCF\xB4\xD9.")); // 2012.11.12 새로 추가된 메세지 (locale_string.txt 에 추가해야 함)
ch->ChatPacket(CHAT_TYPE_COMMAND, "cube fail");
LogManager::instance().CubeLog(ch->GetPlayerID(), ch->GetX(), ch->GetY(),
reward_value->vnum, 0, 0, 0);
@ -576,7 +576,7 @@ bool Cube_make (LPCHARACTER ch)
}
// 큐브에 있는 아이템들을 표시
// 큐브에 있는 아이템들을 표시
void Cube_show_list (LPCHARACTER ch)
{
LPITEM *cube_item;
@ -597,13 +597,13 @@ void Cube_show_list (LPCHARACTER ch)
}
// 인벤토리에 있는 아이템을 큐브에 등록
// 인벤토리에 있는 아이템을 큐브에 등록
void Cube_add_item (LPCHARACTER ch, int cube_index, int inven_index)
{
// 아이템이 있는가?
// 큐브내의 빈자리 찾기
// 큐브세팅
// 메시지 전송
// 아이템이 있는가?
// 큐브내의 빈자리 찾기
// 큐브세팅
// 메시지 전송
LPITEM item;
LPITEM *cube_item;
@ -620,7 +620,7 @@ void Cube_add_item (LPCHARACTER ch, int cube_index, int inven_index)
cube_item = ch->GetCubeItem();
// 이미 다른위치에 등록되었던 아이템이면 기존 indext삭제
// 이미 다른위치에 등록되었던 아이템이면 기존 indext삭제
for (int i=0; i<CUBE_MAX_NUM; ++i)
{
if (item==cube_item[i])
@ -636,14 +636,14 @@ void Cube_add_item (LPCHARACTER ch, int cube_index, int inven_index)
ch->ChatPacket(CHAT_TYPE_INFO, "cube[%d]: inventory[%d]: %s added",
cube_index, inven_index, item->GetName());
// 현재 상자에 올라온 아이템들로 무엇을 만들 수 있는지 클라이언트에 정보 전달
// 을 하고싶었으나 그냥 필요한 골드가 얼마인지 전달
// 현재 상자에 올라온 아이템들로 무엇을 만들 수 있는지 클라이언트에 정보 전달
// 을 하고싶었으나 그냥 필요한 골드가 얼마인지 전달
FN_update_cube_status(ch);
return;
}
// 큐브에있는 아이템을 제거
// 큐브에있는 아이템을 제거
void Cube_delete_item (LPCHARACTER ch, int cube_index)
{
LPITEM item;
@ -664,14 +664,14 @@ void Cube_delete_item (LPCHARACTER ch, int cube_index)
ch->ChatPacket(CHAT_TYPE_INFO, "cube[%d]: cube[%d]: %s deleted",
cube_index, item->GetCell(), item->GetName());
// 현재 상자에 올라온 아이템들로 무엇을 만들 수 있는지 클라이언트에 정보 전달
// 을 하고싶었으나 그냥 필요한 골드가 얼마인지 전달
// 현재 상자에 올라온 아이템들로 무엇을 만들 수 있는지 클라이언트에 정보 전달
// 을 하고싶었으나 그냥 필요한 골드가 얼마인지 전달
FN_update_cube_status(ch);
return;
}
// 아이템 이름을 통해서 순수 이름과 강화레벨을 분리하는 함수 (무쌍검+5 -> 무쌍검, 5)
// 아이템 이름을 통해서 순수 이름과 강화레벨을 분리하는 함수 (무쌍검+5 -> 무쌍검, 5)
SItemNameAndLevel SplitItemNameAndLevelFromName(const std::string& name)
{
int level = 0;
@ -705,7 +705,7 @@ bool FIsLessCubeValue(const CUBE_VALUE& a, const CUBE_VALUE& b)
void Cube_MakeCubeInformationText()
{
// 이제 정리된 큐브 결과 및 재료들의 정보로 클라이언트에 보내 줄 정보로 변환함.
// 이제 정리된 큐브 결과 및 재료들의 정보로 클라이언트에 보내 줄 정보로 변환함.
for (TCubeMapByNPC::iterator iter = cube_info_map.begin(); cube_info_map.end() != iter; ++iter)
{
const DWORD& npcVNUM = iter->first;
@ -717,13 +717,13 @@ void Cube_MakeCubeInformationText()
std::string& infoText = materialInfo.infoText;
// 이놈이 나쁜놈이야
// 이놈이 나쁜놈이야
if (0 < materialInfo.complicateMaterial.size())
{
std::sort(materialInfo.complicateMaterial.begin(), materialInfo.complicateMaterial.end(), FIsLessCubeValue);
std::sort(materialInfo.material.begin(), materialInfo.material.end(), FIsLessCubeValue);
//// 중복되는 재료들을 지움
//// 중복되는 재료들을 지움
for (TCubeValueVector::iterator iter = materialInfo.complicateMaterial.begin(); materialInfo.complicateMaterial.end() != iter; ++iter)
{
for (TCubeValueVector::iterator targetIter = materialInfo.material.begin(); materialInfo.material.end() != targetIter; ++targetIter)
@ -735,7 +735,7 @@ void Cube_MakeCubeInformationText()
}
}
// 72723,1 or 72725,1 or ... 이런 식의 약속된 포맷을 지키는 텍스트를 생성
// 72723,1 or 72725,1 or ... 이런 식의 약속된 포맷을 지키는 텍스트를 생성
for (TCubeValueVector::iterator iter = materialInfo.complicateMaterial.begin(); materialInfo.complicateMaterial.end() != iter; ++iter)
{
char tempBuffer[128];
@ -750,7 +750,7 @@ void Cube_MakeCubeInformationText()
infoText.push_back('&');
}
// 중복되지 않는 일반 재료들도 포맷 생성
// 중복되지 않는 일반 재료들도 포맷 생성
for (TCubeValueVector::iterator iter = materialInfo.material.begin(); materialInfo.material.end() != iter; ++iter)
{
char tempBuffer[128];
@ -760,7 +760,7 @@ void Cube_MakeCubeInformationText()
infoText.erase(infoText.size() - 1);
// 만들 때 골드가 필요하다면 골드정보 추가
// 만들 때 골드가 필요하다면 골드정보 추가
if (0 < materialInfo.gold)
{
char temp[128];
@ -779,7 +779,7 @@ bool Cube_InformationInitialize()
const std::vector<CUBE_VALUE>& rewards = cubeData->reward;
// 하드코딩 ㅈㅅ
// 하드코딩 ㅈㅅ
if (1 != rewards.size())
{
SPDLOG_ERROR("[CubeInfo] WARNING! Does not support multiple rewards (count: {})", rewards.size());
@ -807,13 +807,13 @@ bool Cube_InformationInitialize()
{
SCubeMaterialInfo& existInfo = *iter;
// 이미 중복되는 보상이 등록되어 있다면 아예 다른 조합으로 만드는 것인지,
// 거의 같은 조합인데 특정 부분만 틀린 것인지 구분함.
// 예를들면 특정 부분만 틀린 아이템들은 아래처럼 하나로 묶어서 하나의 결과로 보여주기 위함임:
// 용신지검:
// 무쌍검+5 ~ +9 x 1
// 붉은 칼자루 조각 x1
// 녹색 검장식 조각 x1
// 이미 중복되는 보상이 등록되어 있다면 아예 다른 조합으로 만드는 것인지,
// 거의 같은 조합인데 특정 부분만 틀린 것인지 구분함.
// 예를들면 특정 부분만 틀린 아이템들은 아래처럼 하나로 묶어서 하나의 결과로 보여주기 위함임:
// 용신지검:
// 무쌍검+5 ~ +9 x 1
// 붉은 칼자루 조각 x1
// 녹색 검장식 조각 x1
if (reward.vnum == existInfo.reward.vnum)
{
for (TCubeValueVector::iterator existMaterialIter = existInfo.material.begin(); existInfo.material.end() != existMaterialIter; ++existMaterialIter)
@ -828,8 +828,8 @@ bool Cube_InformationInitialize()
if (0 < existItemInfo.level)
{
// 지금 추가하는 큐브 결과물의 재료와, 기존에 등록되어있던 큐브 결과물의 재료 중
// 중복되는 부분이 있는지 검색한다
// 지금 추가하는 큐브 결과물의 재료와, 기존에 등록되어있던 큐브 결과물의 재료 중
// 중복되는 부분이 있는지 검색한다
for (TCubeValueVector::iterator currentMaterialIter = materialInfo.material.begin(); materialInfo.material.end() != currentMaterialIter; ++currentMaterialIter)
{
TItemTable* currentMaterialProto = ITEM_MANAGER::Instance().GetTable(currentMaterialIter->vnum);
@ -845,7 +845,7 @@ bool Cube_InformationInitialize()
//currentMaterialIter = materialInfo.material.erase(currentMaterialIter);
// TODO: 중복되는 아이템 두 개 이상 검출해야 될 수도 있음
// TODO: 중복되는 아이템 두 개 이상 검출해야 될 수도 있음
break;
}
} // for currentMaterialIter
@ -865,7 +865,7 @@ bool Cube_InformationInitialize()
return true;
}
// 클라이언트에서 서버로 : 현재 NPC가 만들 수 있는 아이템들의 정보(목록)를 요청
// 클라이언트에서 서버로 : 현재 NPC가 만들 수 있는 아이템들의 정보(목록)를 요청
void Cube_request_result_list(LPCHARACTER ch)
{
RETURN_IF_CUBE_IS_NOT_OPENED(ch);
@ -879,7 +879,7 @@ void Cube_request_result_list(LPCHARACTER ch)
std::string& resultText = cube_result_info_map_by_npc[npcVNUM];
// 해당 NPC가 만들 수 있는 목록이 정리된 게 없다면 캐시를 생성
// 해당 NPC가 만들 수 있는 목록이 정리된 게 없다면 캐시를 생성
if (resultText.length() == 0)
{
resultText.clear();
@ -898,7 +898,7 @@ void Cube_request_result_list(LPCHARACTER ch)
resultText.erase(resultText.size() - 1);
// 채팅 패킷의 한계를 넘어가면 에러 남김... 기획자 분들 께 조정해달라고 요청하거나, 나중에 다른 방식으로 바꾸거나...
// 채팅 패킷의 한계를 넘어가면 에러 남김... 기획자 분들 께 조정해달라고 요청하거나, 나중에 다른 방식으로 바꾸거나...
if (resultText.size() - 20 >= CHAT_MAX_LEN)
{
SPDLOG_ERROR("[CubeInfo] Too long cube result list text. (NPC: {}, length: {})", npcVNUM, resultText.size());
@ -908,7 +908,7 @@ void Cube_request_result_list(LPCHARACTER ch)
}
// 현재 NPC가 만들 수 있는 아이템들의 목록을 아래 포맷으로 전송한다.
// 현재 NPC가 만들 수 있는 아이템들의 목록을 아래 포맷으로 전송한다.
// (Server -> Client) /cube r_list npcVNUM resultCount vnum1,count1/vnum2,count2,/vnum3,count3/...
// (Server -> Client) /cube r_list 20383 4 123,1/125,1/128,1/130,5

View File

@ -399,7 +399,7 @@ void DBManager::FlushBilling(bool bForce)
void DBManager::CheckBilling()
{
std::vector<DWORD> vec;
vec.push_back(0); // 카운트를 위해 미리 비워둔다.
vec.push_back(0); // 카운트를 위해 미리 비워둔다.
itertype(m_map_pkLoginData) it = m_map_pkLoginData.begin();
@ -414,7 +414,7 @@ void DBManager::CheckBilling()
}
}
vec[0] = vec.size() - 1; // 비워둔 곳에 사이즈를 넣는다, 사이즈 자신은 제외해야 하므로 -1
vec[0] = vec.size() - 1; // 비워둔 곳에 사이즈를 넣는다, 사이즈 자신은 제외해야 하므로 -1
db_clientdesc->DBPacket(HEADER_GD_BILLING_CHECK, 0, &vec[0], sizeof(DWORD) * vec.size());
}
@ -632,7 +632,7 @@ void DBManager::AnalyzeReturnQuery(SQLMsg * pMsg)
M2_DELETE(pinfo);
break;
}
//위치 변경 - By SeMinZ
//위치 변경 - By SeMinZ
d->SetLogin(pinfo->login);
SPDLOG_DEBUG("QID_AUTH_LOGIN: START {} {}", qi->dwIdent, (void*) get_pointer(d));
@ -758,7 +758,7 @@ void DBManager::AnalyzeReturnQuery(SQLMsg * pMsg)
if (true == LC_IsBrazil())
{
nPasswordDiff = 0; // 브라질 버전에서는 비밀번호 체크를 하지 않는다.
nPasswordDiff = 0; // 브라질 버전에서는 비밀번호 체크를 하지 않는다.
}
if (nPasswordDiff)
@ -789,7 +789,7 @@ void DBManager::AnalyzeReturnQuery(SQLMsg * pMsg)
{
if (LC_IsEurope())
{
//stBlockData >= 0 == 날짜가 BlockDate 보다 미래
//stBlockData >= 0 == 날짜가 BlockDate 보다 미래
if (strncmp(szCreateDate, g_stBlockDate.c_str(), 8) >= 0)
{
LoginFailure(d, "BLKLOGIN");
@ -1315,7 +1315,7 @@ enum EAccountQID
QID_SPAM_DB,
};
// 10분마다 리로드
// 10분마다 리로드
static LPEVENT s_pkReloadSpamEvent = NULL;
EVENTINFO(reload_spam_event_info)

View File

@ -318,12 +318,12 @@ void DESC::Packet(const void * c_pvData, int iSize)
{
assert(iSize > 0);
if (m_iPhase == PHASE_CLOSE) // 끊는 상태면 보내지 않는다.
if (m_iPhase == PHASE_CLOSE) // 끊는 상태면 보내지 않는다.
return;
if (m_stRelayName.length() != 0)
{
// Relay 패킷은 암호화하지 않는다.
// Relay 패킷은 암호화하지 않는다.
TPacketGGRelay p;
p.bHeader = HEADER_GG_RELAY;
@ -369,7 +369,7 @@ void DESC::SetPhase(int _phase)
switch (m_iPhase)
{
case PHASE_CLOSE:
// 메신저가 캐릭터단위가 되면서 삭제
// 메신저가 캐릭터단위가 되면서 삭제
//MessengerManager::instance().Logout(GetAccountTable().login);
m_pInputProcessor = &m_inputClose;
break;
@ -379,8 +379,8 @@ void DESC::SetPhase(int _phase)
break;
case PHASE_SELECT:
// 메신저가 캐릭터단위가 되면서 삭제
//MessengerManager::instance().Logout(GetAccountTable().login); // 의도적으로 break 안검
// 메신저가 캐릭터단위가 되면서 삭제
//MessengerManager::instance().Logout(GetAccountTable().login); // 의도적으로 break 안검
case PHASE_LOGIN:
case PHASE_LOADING:
m_pInputProcessor = &m_inputLogin;

View File

@ -97,7 +97,7 @@ bool CLIENT_DESC::Connect(int iPhaseWhenSucceed)
if (iPhaseWhenSucceed != 0)
m_iPhaseWhenSucceed = iPhaseWhenSucceed;
if (get_global_time() - m_LastTryToConnectTime < 3) // 3초
if (get_global_time() - m_LastTryToConnectTime < 3) // 3초
return false;
m_LastTryToConnectTime = get_global_time();
@ -220,7 +220,7 @@ void CLIENT_DESC::SetPhase(int iPhase)
SPDLOG_DEBUG("DB_SETUP current user {} size {}", p.dwLoginCount, buf.size());
// 파티를 처리할 수 있게 됨.
// 파티를 처리할 수 있게 됨.
CPartyManager::instance().EnablePCParty();
//CPartyManager::instance().SendPartyToDB();
}
@ -301,7 +301,7 @@ void CLIENT_DESC::Update(DWORD t)
void CLIENT_DESC::UpdateChannelStatus(DWORD t, bool fForce)
{
enum {
CHANNELSTATUS_UPDATE_PERIOD = 5*60*1000, // 5분마다
CHANNELSTATUS_UPDATE_PERIOD = 5*60*1000, // 5분마다
};
if (fForce || m_tLastChannelStatusUpdateTime+CHANNELSTATUS_UPDATE_PERIOD < t) {
int iTotal;

View File

@ -53,7 +53,7 @@ int IsValidIP(struct valid_ip* ip_table, const char *host)
DESC_MANAGER::DESC_MANAGER() : m_bDestroyed(false)
{
Initialize();
//NOTE : Destroy 끝에서 Initialize 를 부르는건 또 무슨 짓이냐..-_-; 정말
//NOTE : Destroy 끝에서 Initialize 를 부르는건 또 무슨 짓이냐..-_-; 정말
m_pPackageCrypt = new CClientPackageCryptInfo;
}
@ -146,7 +146,7 @@ RETRY:
LPDESC DESC_MANAGER::AcceptDesc(evconnlistener* listener, evutil_socket_t fd, sockaddr* address)
{
if (!IsValidIP(admin_ip, GetSocketHost(address).c_str())) // admin_ip 에 등록된 IP 는 최대 사용자 수에 구애받지 않는다.
if (!IsValidIP(admin_ip, GetSocketHost(address).c_str())) // admin_ip 에 등록된 IP 는 최대 사용자 수에 구애받지 않는다.
{
if (m_iSocketsConnected >= MAX_ALLOW_USER)
{

View File

@ -172,7 +172,7 @@ bool DragonSoulTable::ReadBasicApplys()
TVecApplys vecApplys;
int n = pChild->GetRowCount();
// BasicApply Group은 Key가 1부터 시작함.
// BasicApply Group은 Key가 1부터 시작함.
for (int j = 1; j <= n; j++)
{
std::stringstream ss;
@ -655,7 +655,7 @@ bool DragonSoulTable::GetWeight(BYTE ds_type, BYTE grade_idx, BYTE step_index, B
return true;
}
}
// default group을 살펴봄.
// default group을 살펴봄.
pDragonSoulGroup = m_pWeightTableNode->GetChildNode("default");
if (NULL != pDragonSoulGroup)
{

View File

@ -1122,7 +1122,7 @@ struct FExitDungeonToStartPosition
{
PIXEL_POSITION posWarp;
// 현재 맵 인덱스를 넣는 것이 아니라 시작하는 맵 인덱스를 넣는다.
// 현재 맵 인덱스를 넣는 것이 아니라 시작하는 맵 인덱스를 넣는다.
if (SECTREE_MANAGER::instance().GetRecallPositionByEmpire(g_start_map[ch->GetEmpire()], ch->GetEmpire(), posWarp))
ch->WarpSet(posWarp.x, posWarp.y);
else
@ -1272,7 +1272,7 @@ void CDungeon::JumpToEliminateLocation()
}
else
{
// 일반 맵으로 워프
// 일반 맵으로 워프
LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
if (!pMap)

View File

@ -97,7 +97,7 @@ void CEntity::PacketView(const void * data, int bytes, LPENTITY except)
FuncPacketView f(data, bytes, except);
// 옵저버 상태에선 내 패킷은 나만 받는다.
// 옵저버 상태에선 내 패킷은 나만 받는다.
if (!m_bIsObserver)
for_each(m_map_view.begin(), m_map_view.end(), f);

View File

@ -98,21 +98,21 @@ class CFuncViewInsert
void operator () (LPENTITY ent)
{
// 오브젝트가 아닌 것은 거리를 계산하여 거리가 멀면 추가하지 않는다.
// 오브젝트가 아닌 것은 거리를 계산하여 거리가 멀면 추가하지 않는다.
if (!ent->IsType(ENTITY_OBJECT))
if (DISTANCE_APPROX(ent->GetX() - m_me->GetX(), ent->GetY() - m_me->GetY()) > dwViewRange)
return;
// 나를 대상에 추가
// 나를 대상에 추가
m_me->ViewInsert(ent);
// 둘다 캐릭터면
// 둘다 캐릭터면
if (ent->IsType(ENTITY_CHARACTER) && m_me->IsType(ENTITY_CHARACTER))
{
LPCHARACTER chMe = (LPCHARACTER) m_me;
LPCHARACTER chEnt = (LPCHARACTER) ent;
// 대상이 NPC면 StateMachine을 킨다.
// 대상이 NPC면 StateMachine을 킨다.
if (chMe->IsPC() && !chEnt->IsPC() && !chEnt->IsWarp() && !chEnt->IsGoto())
chEnt->StartStateMachine();
}
@ -134,13 +134,13 @@ void CEntity::UpdateSectree()
++m_iViewAge;
CFuncViewInsert f(this); // 나를 섹트리에 있는 사람들에게 추가
CFuncViewInsert f(this); // 나를 섹트리에 있는 사람들에게 추가
GetSectree()->ForEachAround(f);
ENTITY_MAP::iterator it, this_it;
//
// m_map_view에서 필요 없는 녀석들 지우기
// m_map_view에서 필요 없는 녀석들 지우기
//
if (m_bObserverModeChange)
{
@ -155,11 +155,11 @@ void CEntity::UpdateSectree()
{
LPENTITY ent = this_it->first;
// 나로 부터 상대방을 지운다.
// 나로 부터 상대방을 지운다.
ent->EncodeRemovePacket(this);
m_map_view.erase(this_it);
// 상대로 부터 나를 지운다.
// 상대로 부터 나를 지운다.
ent->ViewRemove(this, false);
}
else
@ -167,11 +167,11 @@ void CEntity::UpdateSectree()
LPENTITY ent = this_it->first;
// 나로 부터 상대방을 지운다.
// 나로 부터 상대방을 지운다.
//ent->EncodeRemovePacket(this);
//m_map_view.erase(this_it);
// 상대로 부터 나를 지운다.
// 상대로 부터 나를 지운다.
//ent->ViewRemove(this, false);
EncodeRemovePacket(ent);
}
@ -189,11 +189,11 @@ void CEntity::UpdateSectree()
{
LPENTITY ent = this_it->first;
// 나로 부터 상대방을 지운다.
// 나로 부터 상대방을 지운다.
ent->EncodeRemovePacket(this);
m_map_view.erase(this_it);
// 상대로 부터 나를 지운다.
// 상대로 부터 나를 지운다.
ent->ViewRemove(this, false);
}
else
@ -223,11 +223,11 @@ void CEntity::UpdateSectree()
{
LPENTITY ent = this_it->first;
// 나로 부터 상대방을 지운다.
// 나로 부터 상대방을 지운다.
ent->EncodeRemovePacket(this);
m_map_view.erase(this_it);
// 상대로 부터 나를 지운다.
// 상대로 부터 나를 지운다.
ent->ViewRemove(this, false);
}
}

View File

@ -1,8 +1,8 @@
/*
* Filename: event.c
* Description: (timed event)
* Description: (timed event)
*
* Author: (aka. , Cronan), (aka. myevan, )
* Author: (aka. , Cronan), (aka. myevan, )
*/
#include "stdafx.h"
@ -18,12 +18,12 @@ static ObjectPool<EVENT> event_pool;
static CEventQueue cxx_q;
/* 이벤트를 생성하고 리턴한다 */
/* 이벤트를 생성하고 리턴한다 */
LPEVENT event_create_ex(TEVENTFUNC func, event_info_data* info, int when)
{
LPEVENT new_event = NULL;
/* 반드시 다음 pulse 이상의 시간이 지난 후에 부르도록 한다. */
/* 반드시 다음 pulse 이상의 시간이 지난 후에 부르도록 한다. */
if (when < 1)
when = 1;
@ -44,7 +44,7 @@ LPEVENT event_create_ex(TEVENTFUNC func, event_info_data* info, int when)
return (new_event);
}
/* 시스템으로 부터 이벤트를 제거한다 */
/* 시스템으로 부터 이벤트를 제거한다 */
void event_cancel(LPEVENT * ppevent)
{
LPEVENT event;
@ -69,7 +69,7 @@ void event_cancel(LPEVENT * ppevent)
return;
}
// 이미 취소 되었는가?
// 이미 취소 되었는가?
if (!event->q_el)
{
*ppevent = NULL;
@ -98,14 +98,14 @@ void event_reset_time(LPEVENT event, int when)
}
}
/* 이벤트를 실행할 시간에 도달한 이벤트들을 실행한다 */
/* 이벤트를 실행할 시간에 도달한 이벤트들을 실행한다 */
int event_process(int pulse)
{
int new_time;
int num_events = 0;
// event_q 즉 이벤트 큐의 헤드의 시간보다 현재의 pulse 가 적으면 루프문이
// 돌지 않게 된다.
// event_q 즉 이벤트 큐의 헤드의 시간보다 현재의 pulse 가 적으면 루프문이
// 돌지 않게 된다.
while (pulse >= cxx_q.GetTopKey())
{
TQueueElement * pElem = cxx_q.Dequeue();
@ -123,9 +123,9 @@ int event_process(int pulse)
cxx_q.Delete(pElem);
/*
* 0 .
* 0 event
* .
* 0 .
* 0 event
* .
*/
the_event->is_processing = true;
@ -155,7 +155,7 @@ int event_process(int pulse)
return num_events;
}
/* 이벤트가 수행시간을 pulse 단위로 리턴해 준다 */
/* 이벤트가 수행시간을 pulse 단위로 리턴해 준다 */
int event_processing_time(LPEVENT event)
{
int start_time;
@ -167,7 +167,7 @@ int event_processing_time(LPEVENT event)
return (thecore_heart->pulse - start_time);
}
/* 이벤트가 남은 시간을 pulse 단위로 리턴해 준다 */
/* 이벤트가 남은 시간을 pulse 단위로 리턴해 준다 */
int event_time(LPEVENT event)
{
int when;
@ -179,7 +179,7 @@ int event_time(LPEVENT event)
return (when - thecore_heart->pulse);
}
/* 모든 이벤트를 제거한다 */
/* 모든 이벤트를 제거한다 */
void event_destroy(void)
{
TQueueElement * pElem;

View File

@ -1,8 +1,8 @@
/*
* Filename: queue.c
* Description:
* Description:
*
* Author: (aka. , Cronan), (aka. myevan, )
* Author: (aka. , Cronan), (aka. myevan, )
*/
#include "stdafx.h"

View File

@ -16,7 +16,7 @@
void exchange_packet(LPCHARACTER ch, BYTE sub_header, bool is_me, DWORD arg1, TItemPos arg2, DWORD arg3, void * pvData = NULL);
// 교환 패킷
// 교환 패킷
void exchange_packet(LPCHARACTER ch, BYTE sub_header, bool is_me, DWORD arg1, TItemPos arg2, DWORD arg3, void * pvData)
{
if (!ch->GetDesc())
@ -45,10 +45,10 @@ void exchange_packet(LPCHARACTER ch, BYTE sub_header, bool is_me, DWORD arg1, TI
ch->GetDesc()->Packet(&pack_exchg, sizeof(pack_exchg));
}
// 교환을 시작
// 교환을 시작
bool CHARACTER::ExchangeStart(LPCHARACTER victim)
{
if (this == victim) // 자기 자신과는 교환을 못한다.
if (this == victim) // 자기 자신과는 교환을 못한다.
return false;
if (IsObserverMode())
@ -75,7 +75,7 @@ bool CHARACTER::ExchangeStart(LPCHARACTER victim)
//END_PREVENT_TRADE_WINDOW
int iDist = DISTANCE_APPROX(GetX() - victim->GetX(), GetY() - victim->GetY());
// 거리 체크
// 거리 체크
if (iDist >= EXCHANGE_MAX_DISTANCE)
return false;
@ -143,7 +143,7 @@ bool CExchange::AddItem(TItemPos item_pos, BYTE display_pos)
if (!item_pos.IsValidItemPosition())
return false;
// 장비는 교환할 수 없음
// 장비는 교환할 수 없음
if (item_pos.IsEquipPosition())
return false;
@ -163,7 +163,7 @@ bool CExchange::AddItem(TItemPos item_pos, BYTE display_pos)
return false;
}
// 이미 교환창에 추가된 아이템인가?
// 이미 교환창에 추가된 아이템인가?
if (item->IsExchanging())
{
SPDLOG_DEBUG("EXCHANGE under exchanging");
@ -212,7 +212,7 @@ bool CExchange::AddItem(TItemPos item_pos, BYTE display_pos)
return true;
}
// 추가할 공간이 없음
// 추가할 공간이 없음
return false;
}
@ -248,7 +248,7 @@ bool CExchange::AddGold(int gold)
if (GetOwner()->GetGold() < gold)
{
// 가지고 있는 돈이 부족.
// 가지고 있는 돈이 부족.
exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_LESS_GOLD, 0, 0, NPOS, 0);
return false;
}
@ -271,7 +271,7 @@ bool CExchange::AddGold(int gold)
return true;
}
// 돈이 충분히 있는지, 교환하려는 아이템이 실제로 있는지 확인 한다.
// 돈이 충분히 있는지, 교환하려는 아이템이 실제로 있는지 확인 한다.
bool CExchange::Check(int * piItemCount)
{
if (GetOwner()->GetGold() < m_lGold)
@ -325,10 +325,10 @@ bool CExchange::CheckSpace()
s_grid2.Put(i - INVENTORY_MAX_NUM / 2, 1, item->GetSize());
}
// 아... 뭔가 개병신 같지만... 용혼석 인벤을 노멀 인벤 보고 따라 만든 내 잘못이다 ㅠㅠ
// 아... 뭔가 개병신 같지만... 용혼석 인벤을 노멀 인벤 보고 따라 만든 내 잘못이다 ㅠㅠ
static std::vector <WORD> s_vDSGrid(DRAGON_SOUL_INVENTORY_MAX_NUM);
// 일단 용혼석을 교환하지 않을 가능성이 크므로, 용혼석 인벤 복사는 용혼석이 있을 때 하도록 한다.
// 일단 용혼석을 교환하지 않을 가능성이 크므로, 용혼석 인벤 복사는 용혼석이 있을 때 하도록 한다.
bool bDSInitialized = false;
for (i = 0; i < EXCHANGE_ITEM_MAX_NUM; ++i)
@ -411,7 +411,7 @@ bool CExchange::CheckSpace()
return true;
}
// 교환 끝 (아이템과 돈 등을 실제로 옮긴다)
// 교환 끝 (아이템과 돈 등을 실제로 옮긴다)
bool CExchange::Done()
{
int empty_pos, i;
@ -493,7 +493,7 @@ bool CExchange::Done()
return true;
}
// 교환을 동의
// 교환을 동의
bool CExchange::Accept(bool bAccept)
{
if (m_bAccept == bAccept)
@ -501,7 +501,7 @@ bool CExchange::Accept(bool bAccept)
m_bAccept = bAccept;
// 둘 다 동의 했으므로 교환 성립
// 둘 다 동의 했으므로 교환 성립
if (m_bAccept && GetCompany()->m_bAccept)
{
int iItemCount;
@ -513,9 +513,9 @@ bool CExchange::Accept(bool bAccept)
victim->SetExchangeTime();
//END_PREVENT_PORTAL_AFTER_EXCHANGE
// exchange_check 에서는 교환할 아이템들이 제자리에 있나 확인하고,
// 엘크도 충분히 있나 확인한다, 두번째 인자로 교환할 아이템 개수
// 를 리턴한다.
// exchange_check 에서는 교환할 아이템들이 제자리에 있나 확인하고,
// 엘크도 충분히 있나 확인한다, 두번째 인자로 교환할 아이템 개수
// 를 리턴한다.
if (!Check(&iItemCount))
{
GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB5\xB7\xC0\xCC \xBA\xCE\xC1\xB7\xC7\xCF\xB0\xC5\xB3\xAA \xBE\xC6\xC0\xCC\xC5\xDB\xC0\xCC \xC1\xA6\xC0\xDA\xB8\xAE\xBF\xA1 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
@ -523,7 +523,7 @@ bool CExchange::Accept(bool bAccept)
goto EXCHANGE_END;
}
// 리턴 받은 아이템 개수로 상대방의 소지품에 남은 자리가 있나 확인한다.
// 리턴 받은 아이템 개수로 상대방의 소지품에 남은 자리가 있나 확인한다.
if (!CheckSpace())
{
GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xBB\xF3\xB4\xEB\xB9\xE6\xC0\xC7 \xBC\xD2\xC1\xF6\xC7\xB0\xBF\xA1 \xBA\xF3 \xB0\xF8\xB0\xA3\xC0\xCC \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
@ -531,7 +531,7 @@ bool CExchange::Accept(bool bAccept)
goto EXCHANGE_END;
}
// 상대방도 마찬가지로..
// 상대방도 마찬가지로..
if (!GetCompany()->Check(&iItemCount))
{
victim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB5\xB7\xC0\xCC \xBA\xCE\xC1\xB7\xC7\xCF\xB0\xC5\xB3\xAA \xBE\xC6\xC0\xCC\xC5\xDB\xC0\xCC \xC1\xA6\xC0\xDA\xB8\xAE\xBF\xA1 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
@ -556,12 +556,12 @@ bool CExchange::Accept(bool bAccept)
if (Done())
{
if (m_lGold) // 돈이 있을 ??만 저장
if (m_lGold) // 돈이 있을 ??만 저장
GetOwner()->Save();
if (GetCompany()->Done())
{
if (GetCompany()->m_lGold) // 돈이 있을 때만 저장
if (GetCompany()->m_lGold) // 돈이 있을 때만 저장
victim->Save();
// INTERNATIONAL_VERSION
@ -577,14 +577,14 @@ EXCHANGE_END:
}
else
{
// 아니면 accept에 대한 패킷을 보내자.
// 아니면 accept에 대한 패킷을 보내자.
exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_ACCEPT, true, m_bAccept, NPOS, 0);
exchange_packet(GetCompany()->GetOwner(), EXCHANGE_SUBHEADER_GC_ACCEPT, false, m_bAccept, NPOS, 0);
return true;
}
}
// 교환 취소
// 교환 취소
void CExchange::Cancel()
{
exchange_packet(GetOwner(), EXCHANGE_SUBHEADER_GC_END, 0, 0, NPOS, 0);

View File

@ -48,7 +48,7 @@ bool CMemoryTextFileLoader::SplitLine(DWORD dwLine, std::vector<std::string>* ps
pstTokenVector->push_back(c_rstLine.substr(beginPos, endPos - beginPos));
// 추가 코드. 맨뒤에 탭이 있는 경우를 체크한다. - [levites]
// 추가 코드. 맨뒤에 탭이 있는 경우를 체크한다. - [levites]
if (int(c_rstLine.find_first_not_of(c_szDelimeter, basePos)) < 0)
break;
} while (basePos < c_rstLine.length());

View File

@ -205,7 +205,7 @@ void Initialize()
{
SendLog("error! cannot open fishing.txt");
// 백업에 이름이 있으면 리스토어 한다.
// 백업에 이름이 있으면 리스토어 한다.
if (*fish_info_bak[0].name)
{
memcpy(fish_info, fish_info_bak, sizeof(fish_info));
@ -313,7 +313,7 @@ void Initialize()
fish_info[i].length_range[2]);
}
// 확률 계산
// 확률 계산
for (int j = 0; j < MAX_PROB; ++j)
{
g_prob_accumulate[j][0] = fish_info[0].prob[j];
@ -366,7 +366,7 @@ int DetermineFish(LPCHARACTER ch)
// ADD_PREMIUM
if (ch->GetPremiumRemainSeconds(PREMIUM_FISH_MIND) > 0 ||
ch->IsEquipUniqueGroup(UNIQUE_GROUP_FISH_MIND)) // 월간어심 착용시 고급 물고기 확률 상승
ch->IsEquipUniqueGroup(UNIQUE_GROUP_FISH_MIND)) // 월간어심 착용시 고급 물고기 확률 상승
{
if (quest::CQuestManager::instance().GetEventFlag("manwoo") != 0)
prob_idx = 3;
@ -394,7 +394,7 @@ int DetermineFish(LPCHARACTER ch)
return 0;
}
if (g_iUseLocale) // 중국에서는 금덩어리, 금열쇠, 은열쇠 나오지 않게 함
if (g_iUseLocale) // 중국에서는 금덩어리, 금열쇠, 은열쇠 나오지 않게 함
{
DWORD vnum = fish_info[fish_idx].vnum;
@ -437,7 +437,7 @@ void FishingPractice(LPCHARACTER ch)
LPITEM rod = ch->GetWear(WEAR_WEAPON);
if (rod && rod->GetType() == ITEM_ROD)
{
// 최대 수련도가 아닌 경우 낚시대 수련
// 최대 수련도가 아닌 경우 낚시대 수련
if ( rod->GetRefinedVnum()>0 && rod->GetSocket(0) < rod->GetValue(2) && Random::get(1,rod->GetValue(1))==1 )
{
rod->SetSocket(0, rod->GetSocket(0) + 1);
@ -449,14 +449,14 @@ void FishingPractice(LPCHARACTER ch)
}
}
}
// 미끼를 뺀다
// 미끼를 뺀다
rod->SetSocket(2, 0);
}
bool PredictFish(LPCHARACTER ch)
{
// ADD_PREMIUM
// 어심환
// 어심환
if (ch->FindAffect(AFFECT_FISH_MIND_PILL) ||
ch->GetPremiumRemainSeconds(PREMIUM_FISH_MIND) > 0 ||
ch->IsEquipUniqueGroup(UNIQUE_GROUP_FISH_MIND))
@ -491,7 +491,7 @@ EVENTFUNC(fishing_event)
switch (info->step)
{
case 0: // 흔들리기 또는 떡밥만 날아감
case 0: // 흔들리기 또는 떡밥만 날아감
++info->step;
//info->ch->Motion(MOTION_FISHING_SIGN);
@ -600,7 +600,7 @@ int GetFishLength(int fish_id)
void Take(fishing_event_info* info, LPCHARACTER ch)
{
if (info->step == 1) // 고기가 걸린 상태면..
if (info->step == 1) // 고기가 걸린 상태면..
{
int ms = (int) ((get_dword_time() - info->hang_time));
DWORD item_vnum = 0;
@ -611,9 +611,9 @@ void Take(fishing_event_info* info, LPCHARACTER ch)
switch (ret)
{
case -2: // 잡히지 않은 경우
case -3: // 난이도 때문에 실패
case -1: // 시간 확률 때문에 실패
case -2: // 잡히지 않은 경우
case -3: // 난이도 때문에 실패
case -1: // 시간 확률 때문에 실패
//ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB0\xED\xB1\xE2\xB0\xA1 \xB9\xCC\xB3\xA2\xB8\xB8 \xBB\xA9\xB8\xD4\xB0\xED \xC0\xEC\xBD\xCE\xB0\xD4 \xB5\xB5\xB8\xC1\xC4\xA8\xB4\xCF\xB4\xD9."));
{
int map_idx = ch->GetMapIndex();
@ -652,7 +652,7 @@ void Take(fishing_event_info* info, LPCHARACTER ch)
if (quest::CQuestManager::instance().GetEventFlag("fishevent") > 0 && (info->fish_id == 5 || info->fish_id == 6))
{
// 이벤트 중이므로 기록한다.
// 이벤트 중이므로 기록한다.
TPacketGDHighscore p;
p.dwPID = ch->GetPlayerID();
@ -758,7 +758,7 @@ void UseFish(LPCHARACTER ch, LPITEM item)
{
int idx = item->GetVnum() - fish_info[2].vnum+2;
// 피라미 사용불가, 살아있는게 아닌건 사용불가
// 피라미 사용불가, 살아있는게 아닌건 사용불가
if (idx<=1 || idx >= MAX_FISH)
return;
@ -769,12 +769,12 @@ void UseFish(LPCHARACTER ch, LPITEM item)
if (r >= 4001)
{
// 죽은 물고기
// 죽은 물고기
ch->AutoGiveItem(fish_info[idx].dead_vnum);
}
else if (r >= 2001)
{
// 생선뼈
// 생선뼈
ch->AutoGiveItem(FISH_BONE_VNUM);
}
else
@ -878,14 +878,14 @@ int RealRefineRod(LPCHARACTER ch, LPITEM item)
if (pkNewItem)
{
BYTE bCell = rod->GetCell();
// 낚시대 개량 성공
// 낚시대 개량 성공
ITEM_MANAGER::instance().RemoveItem(rod, "REMOVE (REFINE FISH_ROD)");
pkNewItem->AddToCharacter(ch, TItemPos (INVENTORY, bCell));
LogManager::instance().ItemLog(ch, pkNewItem, "REFINE FISH_ROD SUCCESS", pkNewItem->GetName());
return 1;
}
// 낚시대 개량 실패
// 낚시대 개량 실패
return 2;
}
else
@ -896,14 +896,14 @@ int RealRefineRod(LPCHARACTER ch, LPITEM item)
if (pkNewItem)
{
BYTE bCell = rod->GetCell();
// 낚시대 개량에 성공
// 낚시대 개량에 성공
ITEM_MANAGER::instance().RemoveItem(rod, "REMOVE (REFINE FISH_ROD)");
pkNewItem->AddToCharacter(ch, TItemPos(INVENTORY, bCell));
LogManager::instance().ItemLog(ch, pkNewItem, "REFINE FISH_ROD FAIL", pkNewItem->GetName());
return 0;
}
// 낚시대 개량 실패
// 낚시대 개량 실패
return 2;
}
}

View File

@ -65,7 +65,7 @@ BYTE gm_new_get_level( const char * name, const char * host, const char* account
return GM_PLAYER;
// GERMAN_GM_NOT_CHECK_HOST
// 독일 버전은 호스트 체크를 하지 않는다.
// 독일 버전은 호스트 체크를 하지 않는다.
if ( LC_IsEurope() && !LC_IsTaiwan() || LC_IsSingapore() )
{
if (account)

View File

@ -200,7 +200,7 @@ bool CGroupNode::GetRow(const std::string & c_rstrRowKey, OUT const CGroupNode::
return true;
}
// 참고로, idx랑 txt에 쓰여진 순서랑 관계 없음.
// 참고로, idx랑 txt에 쓰여진 순서랑 관계 없음.
bool CGroupNode::GetRow(int idx, OUT const CGroupNode::CGroupNodeRow ** ppRow) const
{
if (idx >= m_map_rows.size())
@ -223,7 +223,7 @@ bool CGroupNode::GetGroupRow(const std::string& stGroupName, const std::string&
if (pChildGroup->GetRow(stRow, ppRow))
return true;
}
// default group을 살펴봄.
// default group을 살펴봄.
pChildGroup = GetChildNode("default");
if (NULL != pChildGroup)
{

View File

@ -418,7 +418,7 @@ void CGuild::SendListPacket(LPCHARACTER ch)
Count (byte)
[
...
name_flag 1 -
name_flag 1 -
name CHARACTER_NAME_MAX_LEN+1
] * Count
@ -560,7 +560,7 @@ void CGuild::LoadGuildMemberData(SQLMsg* pmsg)
void CGuild::LoadGuildGradeData(SQLMsg* pmsg)
{
/*
// 15개 아닐 가능성 존재
// 15개 아닐 가능성 존재
if (pmsg->Get()->iNumRows != 15)
{
SPDLOG_ERROR("Query failed: getting guild grade data. GuildID({})", GetID());
@ -698,7 +698,7 @@ void CGuild::__P2PUpdateGrade(SQLMsg* pmsg)
grade--;
// 등급 명칭이 현재와 다르다면 업데이트
// 등급 명칭이 현재와 다르다면 업데이트
if (0 != strcmp(m_data.grade_array[grade].grade_name, name))
{
strlcpy(m_data.grade_array[grade].grade_name, name, sizeof(m_data.grade_array[grade].grade_name));
@ -1084,7 +1084,7 @@ void CGuild::RefreshCommentForce(DWORD player_id)
d->RawPacket(szName, sizeof(szName));
if (i == pmsg->Get()->uiNumRows - 1)
d->Packet(szContent, sizeof(szContent)); // 마지막 줄이면 보내기
d->Packet(szContent, sizeof(szContent)); // 마지막 줄이면 보내기
else
d->RawPacket(szContent, sizeof(szContent));
}
@ -1263,7 +1263,7 @@ void CGuild::UseSkill(DWORD dwVnum, LPCHARACTER ch, DWORD pid)
if ((pkSk->dwFlag & SKILL_FLAG_SELFONLY))
{
// 이미 걸려 있으므로 사용하지 않음.
// 이미 걸려 있으므로 사용하지 않음.
if (ch->FindAffect(pkSk->dwVnum))
return;
@ -1315,7 +1315,7 @@ void CGuild::UseSkill(DWORD dwVnum, LPCHARACTER ch, DWORD pid)
switch (dwVnum)
{
case GUILD_SKILL_TELEPORT:
// 현재 서버에 있는 사람을 먼저 시도.
// 현재 서버에 있는 사람을 먼저 시도.
SendDBSkillUpdate(-iNeededSP);
if ((victim = (CHARACTER_MANAGER::instance().FindByPID(pid))))
ch->WarpSet(victim->GetX(), victim->GetY());
@ -1323,10 +1323,10 @@ void CGuild::UseSkill(DWORD dwVnum, LPCHARACTER ch, DWORD pid)
{
if (m_memberP2POnline.find(pid) != m_memberP2POnline.end())
{
// 다른 서버에 로그인된 사람이 있음 -> 메시지 보내 좌표를 받아오자
// 1. A.pid, B.pid 를 뿌림
// 2. B.pid를 가진 서버가 뿌린서버에게 A.pid, 좌표 를 보냄
// 3. 워프
// 다른 서버에 로그인된 사람이 있음 -> 메시지 보내 좌표를 받아오자
// 1. A.pid, B.pid 를 뿌림
// 2. B.pid를 가진 서버가 뿌린서버에게 A.pid, 좌표 를 보냄
// 3. 워프
CCI * pcci = P2P_MANAGER::instance().FindByPID(pid);
if (pcci->bChannel != g_bChannel)
@ -1897,11 +1897,11 @@ bool CGuild::HasLand()
}
// GUILD_JOIN_BUG_FIX
/// 길드 초대 event 정보
/// 길드 초대 event 정보
EVENTINFO(TInviteGuildEventInfo)
{
DWORD dwInviteePID; ///< 초대받은 character 의 PID
DWORD dwGuildID; ///< 초대한 Guild 의 ID
DWORD dwInviteePID; ///< 초대받은 character 의 PID
DWORD dwGuildID; ///< 초대한 Guild 의 ID
TInviteGuildEventInfo()
: dwInviteePID( 0 )
@ -1911,8 +1911,8 @@ EVENTINFO(TInviteGuildEventInfo)
};
/**
* event callback .
* event .
* event callback .
* event .
*/
EVENTFUNC( GuildInviteEvent )
{
@ -1989,7 +1989,7 @@ void CGuild::Invite( LPCHARACTER pchInviter, LPCHARACTER pchInvitee )
return;
//
// 이벤트 생성
// 이벤트 생성
//
TInviteGuildEventInfo* pInfo = AllocEventInfo<TInviteGuildEventInfo>();
pInfo->dwInviteePID = pchInvitee->GetPlayerID();
@ -1998,7 +1998,7 @@ void CGuild::Invite( LPCHARACTER pchInviter, LPCHARACTER pchInvitee )
m_GuildInviteEventMap.insert(EventMap::value_type(pchInvitee->GetPlayerID(), event_create(GuildInviteEvent, pInfo, PASSES_PER_SEC(10))));
//
// 초대 받는 character 에게 초대 패킷 전송
// 초대 받는 character 에게 초대 패킷 전송
//
DWORD gid = GetID();

View File

@ -504,7 +504,7 @@ void CGuildManager::RequestWarOver(DWORD dwGuild1, DWORD dwGuild2, DWORD dwGuild
TPacketGuildWar p;
p.bWar = GUILD_WAR_OVER;
// 길드전이 끝나도 보상은 없다.
// 길드전이 끝나도 보상은 없다.
//p.lWarPrice = lReward;
p.lWarPrice = 0;
p.bType = dwGuildWinner == 0 ? 1 : 0; // bType == 1 means draw for this packet.
@ -952,7 +952,7 @@ void CGuildManager::ChangeMaster(DWORD dwGID)
iter->second->Load(dwGID);
}
// 업데이트된 정보 보내주기
// 업데이트된 정보 보내주기
DBManager::instance().FuncQuery(std::bind1st(std::mem_fun(&CGuild::SendGuildDataUpdateToAllMember), iter->second),
"SELECT 1");

View File

@ -140,12 +140,12 @@ DWORD CGuild::GetGuildWarMapIndex(DWORD dwOppGID)
return git->second.map_index;
}
bool CGuild::CanStartWar(BYTE bGuildWarType) // 타입에 따라 다른 조건이 생길 수도 있음
bool CGuild::CanStartWar(BYTE bGuildWarType) // 타입에 따라 다른 조건이 생길 수도 있음
{
if (bGuildWarType >= GUILD_WAR_TYPE_MAX_NUM)
return false;
// 테스트시에는 인원수를 확인하지 않는다.
// 테스트시에는 인원수를 확인하지 않는다.
if (test_server || quest::CQuestManager::instance().GetEventFlag("guild_war_test") != 0)
return GetLadderPoint() > 0;
@ -317,7 +317,7 @@ void CGuild::RequestDeclareWar(DWORD dwOppGID, BYTE type)
return;
}
// 패킷 보내기 to another server
// 패킷 보내기 to another server
TPacketGuildWar p;
p.bType = type;
p.bWar = GUILD_WAR_SEND_DECLARE;
@ -336,7 +336,7 @@ void CGuild::RequestDeclareWar(DWORD dwOppGID, BYTE type)
if (saved_type == GUILD_WAR_TYPE_FIELD)
{
// 선전포고 한것을 받아들였다.
// 선전포고 한것을 받아들였다.
TPacketGuildWar p;
p.bType = saved_type;
p.bWar = GUILD_WAR_ON_WAR;
@ -441,14 +441,14 @@ void CGuild::StartWar(DWORD dwOppGID)
bool CGuild::WaitStartWar(DWORD dwOppGID)
{
//자기자신이면
//자기자신이면
if (dwOppGID == GetID())
{
SPDLOG_ERROR("GuildWar.WaitStartWar.DECLARE_WAR_SELF id({} -> {})", GetID(), dwOppGID);
return false;
}
//상대방 길드 TGuildWar 를 얻어온다.
//상대방 길드 TGuildWar 를 얻어온다.
itertype(m_EnemyGuild) it = m_EnemyGuild.find(dwOppGID);
if (it == m_EnemyGuild.end())
{
@ -456,7 +456,7 @@ bool CGuild::WaitStartWar(DWORD dwOppGID)
return false;
}
//레퍼런스에 등록하고
//레퍼런스에 등록하고
TGuildWar & gw(it->second);
if (gw.state == GUILD_WAR_WAIT_START)
@ -465,10 +465,10 @@ bool CGuild::WaitStartWar(DWORD dwOppGID)
return false;
}
//상태를 저장한다.
//상태를 저장한다.
gw.state = GUILD_WAR_WAIT_START;
//상대편의 길드 클래스 포인터를 얻어오고
//상대편의 길드 클래스 포인터를 얻어오고
CGuild* g = CGuildManager::instance().FindGuild(dwOppGID);
if (!g)
{
@ -481,14 +481,14 @@ bool CGuild::WaitStartWar(DWORD dwOppGID)
// END_OF_GUILDWAR_INFO
// 필드형이면 맵생성 안함
// 필드형이면 맵생성 안함
if (gw.type == GUILD_WAR_TYPE_FIELD)
{
SPDLOG_DEBUG("GuildWar.WaitStartWar.FIELD_TYPE id({} -> {})", GetID(), dwOppGID);
return true;
}
// 전쟁 서버 인지 확인
// 전쟁 서버 인지 확인
SPDLOG_DEBUG("GuildWar.WaitStartWar.CheckWarServer id({} -> {}), type({}), map({})",
GetID(), dwOppGID, gw.type, rkGuildWarInfo.lMapIndex);
@ -505,7 +505,7 @@ bool CGuild::WaitStartWar(DWORD dwOppGID)
if (id1 > id2)
std::swap(id1, id2);
//워프 맵을 생성
//워프 맵을 생성
DWORD lMapIndex = CWarMapManager::instance().CreateWarMap(rkGuildWarInfo, id1, id2);
if (!lMapIndex)
{
@ -516,10 +516,10 @@ bool CGuild::WaitStartWar(DWORD dwOppGID)
SPDLOG_DEBUG("GuildWar.WaitStartWar.CreateMap id({} vs {}), type({}), map({}) -> map_inst({})", id1, id2, gw.type, rkGuildWarInfo.lMapIndex, lMapIndex);
//길드전 정보에 맵인덱스를 세팅
//길드전 정보에 맵인덱스를 세팅
gw.map_index = lMapIndex;
//양쪽에 등록(?)
//양쪽에 등록(?)
SetGuildWarMapIndex(dwOppGID, lMapIndex);
g->SetGuildWarMapIndex(GetID(), lMapIndex);
@ -546,7 +546,7 @@ void CGuild::RequestRefuseWar(DWORD dwOppGID)
if (it != m_EnemyGuild.end() && it->second.state == GUILD_WAR_RECV_DECLARE)
{
// 선전포고를 거절했다.
// 선전포고를 거절했다.
TPacketGuildWar p;
p.bWar = GUILD_WAR_REFUSE;
p.dwGuildFrom = GetID();

View File

@ -14,10 +14,10 @@ const int HORSE_STAMINA_REGEN_INTERVAL = 12 * 60;
THorseStat c_aHorseStat[HORSE_MAX_LEVEL+1] =
/*
int iMinLevel; // 탑승할 수 있는 최소 레벨
int iMinLevel; // 탑승할 수 있는 최소 레벨
int iNPCRace;
int iMaxHealth; // 말의 최대 체력
int iMaxStamina; // 말의 최대 스테미너
int iMaxHealth; // 말의 최대 체력
int iMaxStamina; // 말의 최대 스테미너
int iST;
int iDX;
int iHT;
@ -29,7 +29,7 @@ THorseStat c_aHorseStat[HORSE_MAX_LEVEL+1] =
*/
{
{ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 25, 20101, 3, 4, 26, 35, 18, 9, 54, 43, 64, 32 }, // 1 (초급)
{ 25, 20101, 3, 4, 26, 35, 18, 9, 54, 43, 64, 32 }, // 1 (초급)
{ 25, 20101, 4, 4, 27, 36, 18, 9, 55, 44, 66, 33 },
{ 25, 20101, 5, 5, 28, 38, 19, 9, 56, 44, 67, 33 },
{ 25, 20101, 7, 5, 29, 39, 19, 10, 57, 45, 68, 34 },
@ -39,7 +39,7 @@ THorseStat c_aHorseStat[HORSE_MAX_LEVEL+1] =
{ 25, 20101, 12, 7, 33, 44, 22, 11, 61, 48, 73, 36 },
{ 25, 20101, 13, 8, 34, 45, 22, 11, 62, 49, 74, 37 },
{ 25, 20101, 15, 10, 35, 46, 23, 12, 63, 50, 75, 37 },
{ 35, 20104, 18, 30, 40, 53, 27, 13, 69, 55, 82, 41 }, // 11 (중급)
{ 35, 20104, 18, 30, 40, 53, 27, 13, 69, 55, 82, 41 }, // 11 (중급)
{ 35, 20104, 19, 35, 41, 54, 27, 14, 70, 56, 84, 42 },
{ 35, 20104, 21, 40, 42, 56, 28, 14, 71, 56, 85, 42 },
{ 35, 20104, 22, 50, 43, 57, 28, 14, 72, 57, 86, 43 },
@ -49,7 +49,7 @@ THorseStat c_aHorseStat[HORSE_MAX_LEVEL+1] =
{ 35, 20104, 28, 70, 46, 62, 31, 15, 76, 60, 91, 45 },
{ 35, 20104, 30, 80, 47, 63, 31, 16, 77, 61, 92, 46 },
{ 35, 20104, 32, 100, 48, 64, 32, 16, 78, 62, 93, 46 },
{ 50, 20107, 35, 120, 53, 71, 36, 18, 84, 67, 100, 50 }, // 21 (고급)
{ 50, 20107, 35, 120, 53, 71, 36, 18, 84, 67, 100, 50 }, // 21 (고급)
{ 50, 20107, 36, 125, 55, 74, 37, 18, 86, 68, 103, 51 },
{ 50, 20107, 37, 130, 57, 76, 38, 19, 88, 70, 105, 52 },
{ 50, 20107, 38, 135, 59, 78, 39, 20, 90, 72, 108, 54 },
@ -117,7 +117,7 @@ bool CHorseRider::ReviveHorse()
m_Horse.sHealth = c_aHorseStat[level].iMaxHealth;
m_Horse.sStamina = c_aHorseStat[level].iMaxStamina;
// 2005.03.24.ipkn.말 살린후 다시 죽는 현상 수정
// 2005.03.24.ipkn.말 살린후 다시 죽는 현상 수정
ResetHorseHealthDropTime();
StartStaminaRegenEvent();
@ -138,11 +138,11 @@ short CHorseRider::GetHorseMaxStamina()
void CHorseRider::FeedHorse()
{
// 말을 가지고 살아있을때만
// 말을 가지고 살아있을때만
if (GetHorseLevel() > 0 && GetHorseHealth() > 0)
{
UpdateHorseHealth(+1);
// 20050324. ipkn 말 먹였을때도 체력 감소 딜레이를 늘린다.
// 20050324. ipkn 말 먹였을때도 체력 감소 딜레이를 늘린다.
ResetHorseHealthDropTime();
}
}
@ -159,7 +159,7 @@ void CHorseRider::UpdateHorseDataByLogoff(DWORD dwLogoffTime)
return;
if (dwLogoffTime >= 12 * 60)
UpdateHorseStamina(dwLogoffTime / 12 / 60, false); // 로그오프 12분당 1씩 회복
UpdateHorseStamina(dwLogoffTime / 12 / 60, false); // 로그오프 12분당 1씩 회복
}
void CHorseRider::UpdateHorseStamina(int iStamina, bool bSend)

View File

@ -72,7 +72,7 @@ bool CInputProcessor::Process(LPDESC lpDesc, const void * c_pvOrig, int iBytes,
BYTE bHeader = (BYTE) *(c_pData);
const char * c_pszName;
if (bHeader == 0) // 암호화 처리가 있으므로 0번 헤더는 스킵한다.
if (bHeader == 0) // 암호화 처리가 있으므로 0번 헤더는 스킵한다.
iPacketLen = 1;
else if (!m_pPacketInfo->Get(bHeader, &iPacketLen, &c_pszName))
{
@ -249,7 +249,7 @@ ACMD(do_block_chat);
int CInputHandshake::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
{
if (bHeader == 10) // 엔터는 무시
if (bHeader == 10) // 엔터는 무시
return 0;
if (bHeader == HEADER_CG_TEXT)
@ -257,7 +257,7 @@ int CInputHandshake::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
++c_pData;
const char * c_pSep;
if (!(c_pSep = strchr(c_pData, '\n'))) // \n을 찾는다.
if (!(c_pSep = strchr(c_pData, '\n'))) // \n을 찾는다.
return -1;
if (*(c_pSep - 1) == '\r')
@ -356,7 +356,7 @@ int CInputHandshake::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
else if (!stBuf.compare(0,15,"DELETE_AWARDID "))
{
char szTmp[64];
std::string msg = stBuf.substr(15,26); // item_award의 id범위?
std::string msg = stBuf.substr(15,26); // item_award의 id범위?
TPacketDeleteAwardID p;
p.dwID = (DWORD)(atoi(msg.c_str()));
@ -371,7 +371,7 @@ int CInputHandshake::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
if (d->IsAdminMode())
{
// 어드민 명령들
// 어드민 명령들
if (!stBuf.compare(0, 7, "NOTICE "))
{
std::string msg = stBuf.substr(7, 50);
@ -519,7 +519,7 @@ int CInputHandshake::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
std::string strPrivEmpire;
is >> strPrivEmpire >> empire >> type >> value >> duration;
// 최대치 10배
// 최대치 10배
value = std::clamp(value, 0, 1000);
stResult = "PRIV_EMPIRE FAIL";
@ -534,7 +534,7 @@ int CInputHandshake::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
{
stResult = "PRIV_EMPIRE SUCCEED";
// 시간 단위로 변경
// 시간 단위로 변경
duration = duration * (60 * 60);
SPDLOG_DEBUG("_give_empire_privileage(empire={}, type={}, value={}, duration={}) by web",
@ -569,13 +569,13 @@ int CInputHandshake::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
{
if (!guild_mark_server)
{
// 끊어버려! - 마크 서버가 아닌데 마크를 요청하려고?
// 끊어버려! - 마크 서버가 아닌데 마크를 요청하려고?
SPDLOG_ERROR("Guild Mark login requested but i'm not a mark server!");
d->SetPhase(PHASE_CLOSE);
return 0;
}
// 무조건 인증 --;
// 무조건 인증 --;
SPDLOG_DEBUG("MARK_SERVER: Login");
d->SetPhase(PHASE_LOGIN);
return 0;

View File

@ -23,11 +23,11 @@ bool FN_IS_VALID_LOGIN_STRING(const char *str)
for (tmp = str; *tmp; ++tmp)
{
// 알파벳과 수자만 허용
// 알파벳과 수자만 허용
if (isdigit(*tmp) || isalpha(*tmp))
continue;
// 캐나다는 몇몇 특수문자 허용
// 캐나다는 몇몇 특수문자 허용
if (LC_IsCanada())
{
switch (*tmp)
@ -111,7 +111,7 @@ void CInputAuth::Login(LPDESC d, const char * c_pData)
return;
}
// string 무결성을 위해 복사
// string 무결성을 위해 복사
char login[LOGIN_MAX_LEN + 1];
trim_and_lower(pinfo->login, login, sizeof(login));

View File

@ -135,7 +135,7 @@ void CInputDB::LoginSuccess(DWORD dwHandle, const char *data)
return;
}
if (strcmp(pTab->status, "OK")) // OK가 아니면
if (strcmp(pTab->status, "OK")) // OK가 아니면
{
SPDLOG_DEBUG("CInputDB::LoginSuccess - status[{}] is not OK [{}]", pTab->status, pTab->login);
@ -158,7 +158,7 @@ void CInputDB::LoginSuccess(DWORD dwHandle, const char *data)
d->BindAccountTable(pTab);
if (!bFound) // 캐릭터가 없으면 랜덤한 제국으로 보낸다.. -_-
if (!bFound) // 캐릭터가 없으면 랜덤한 제국으로 보낸다.. -_-
{
TPacketGCEmpire pe;
pe.bHeader = HEADER_GC_EMPIRE;
@ -231,7 +231,7 @@ void CInputDB::PlayerCreateSuccess(LPDESC d, const char * data)
d->Packet(&pack, sizeof(TPacketGCPlayerCreateSuccess));
// 기본 무기와 귀환부를 지급
// 기본 무기와 귀환부를 지급
TPlayerItem t;
memset(&t, 0, sizeof(t));
@ -241,10 +241,10 @@ void CInputDB::PlayerCreateSuccess(LPDESC d, const char * data)
t.count = 1;
t.owner = r_Tab.players[pPacketDB->bAccountCharacterIndex].dwID;
//무사: 자인갑+3,철편투구+3,금편신발+3,남만도+3,백금목걸이+3, 흑단귀걸이+3, 소산부+3, 오각패+3, 흑단팔찌+3
//자객:영린+3,연환두건+3,금편신발+3,마안도+3,화안궁+3,옥목걸이+3, 옥귀걸이+3, 오각패+3, 흑단팔찌+3
//수라:음양갑+3,애희투구+3,금편신발+3,남만도+3,진주목걸이+3, 백금귀걸이+3, 오각패+3, 흑단팔찌+3
//무당:서천의+3,태을모+3,금편신발+3,자린선+3,매화령+3,진주목걸이+3, 백금귀걸이+3, 오각패+3, 흑단팔찌+3
//무사: 자인갑+3,철편투구+3,금편신발+3,남만도+3,백금목걸이+3, 흑단귀걸이+3, 소산부+3, 오각패+3, 흑단팔찌+3
//자객:영린+3,연환두건+3,금편신발+3,마안도+3,화안궁+3,옥목걸이+3, 옥귀걸이+3, 오각패+3, 흑단팔찌+3
//수라:음양갑+3,애희투구+3,금편신발+3,남만도+3,진주목걸이+3, 백금귀걸이+3, 오각패+3, 흑단팔찌+3
//무당:서천의+3,태을모+3,금편신발+3,자린선+3,매화령+3,진주목걸이+3, 백금귀걸이+3, 오각패+3, 흑단팔찌+3
struct SInitialItem
{
@ -347,7 +347,7 @@ void CInputDB::PlayerLoad(LPDESC d, const char * data)
{
lMapIndex = SECTREE_MANAGER::instance().GetMapIndex(pTab->x, pTab->y);
if (lMapIndex == 0) // 좌표를 찾을 수 없다.
if (lMapIndex == 0) // 좌표를 찾을 수 없다.
{
lMapIndex = EMPIRE_START_MAP(d->GetAccountTable().bEmpire);
pos.x = EMPIRE_START_X(d->GetAccountTable().bEmpire);
@ -361,11 +361,11 @@ void CInputDB::PlayerLoad(LPDESC d, const char * data)
}
pTab->lMapIndex = lMapIndex;
// Private 맵에 있었는데, Private 맵이 사라진 상태라면 출구로 돌아가야 한다.
// Private 맵에 있었는데, Private 맵이 사라진 상태라면 출구로 돌아가야 한다.
// ----
// 근데 출구로 돌아가야 한다면서... 왜 출구가 아니라 private map 상에 대응되는 pulic map의 위치를 찾냐고...
// 역사를 모르니... 또 하드코딩 한다.
// 아귀동굴이면, 출구로...
// 근데 출구로 돌아가야 한다면서... 왜 출구가 아니라 private map 상에 대응되는 pulic map의 위치를 찾냐고...
// 역사를 모르니... 또 하드코딩 한다.
// 아귀동굴이면, 출구로...
// by rtsummit
if (!SECTREE_MANAGER::instance().GetValidLocation(pTab->lMapIndex, pTab->x, pTab->y, lMapIndex, pos, d->GetEmpire()))
{
@ -479,11 +479,11 @@ void CInputDB::Boot(const char* data)
{
signal_timer_disable();
// 패킷 사이즈 체크
// 패킷 사이즈 체크
DWORD dwPacketSize = decode_4bytes(data);
data += 4;
// 패킷 버전 체크
// 패킷 버전 체크
BYTE bVersion = decode_byte(data);
data += 1;
@ -802,7 +802,7 @@ void CInputDB::Boot(const char* data)
data += size * sizeof(TItemIDRangeTable);
//ADMIN_MANAGER
//관리자 등록
//관리자 등록
int ChunkSize = decode_2bytes(data );
data += 2;
int HostSize = decode_2bytes(data );
@ -1170,7 +1170,7 @@ void CInputDB::SafeboxLoad(LPDESC d, const char * c_pData)
// END_OF_ADD_PREMIUM
//if (d->GetCharacter()->IsEquipUniqueItem(UNIQUE_ITEM_SAFEBOX_EXPAND))
//bSize = 3; // 창고확장권
//bSize = 3; // 창고확장권
//d->GetCharacter()->LoadSafebox(p->bSize * SAFEBOX_PAGE_SIZE, p->dwGold, p->wItemCount, (TPlayerItem *) (c_pData + sizeof(TSafeboxTable)));
d->GetCharacter()->LoadSafebox(bSize * SAFEBOX_PAGE_SIZE, p->dwGold, p->wItemCount, (TPlayerItem *) (c_pData + sizeof(TSafeboxTable)));
@ -1190,7 +1190,7 @@ void CInputDB::SafeboxChangeSize(LPDESC d, const char * c_pData)
}
//
// @version 05/06/20 Bang2ni - ReqSafeboxLoad 의 취소
// @version 05/06/20 Bang2ni - ReqSafeboxLoad 의 취소
//
void CInputDB::SafeboxWrongPassword(LPDESC d)
{
@ -1250,7 +1250,7 @@ void CInputDB::LoginAlready(LPDESC d, const char * c_pData)
if (!d)
return;
// INTERNATIONAL_VERSION 이미 접속중이면 접속 끊음
// INTERNATIONAL_VERSION 이미 접속중이면 접속 끊음
{
TPacketDGLoginAlready * p = (TPacketDGLoginAlready *) c_pData;
@ -1730,11 +1730,11 @@ void CInputDB::AuthLogin(LPDESC d, const char * c_pData)
if (bResult)
{
// Panama 암호화 팩에 필요한 키 보내기
// Panama 암호화 팩에 필요한 키 보내기
SendPanamaList(d);
ptoc.dwLoginKey = d->GetLoginKey();
//NOTE: AuthSucess보다 먼저 보내야지 안그러면 PHASE Close가 되서 보내지지 않는다.-_-
//NOTE: AuthSucess보다 먼저 보내야지 안그러면 PHASE Close가 되서 보내지지 않는다.-_-
//Send Client Package CryptKey
{
DESC_MANAGER::instance().SendClientPackageCryptKey(d);
@ -1762,7 +1762,7 @@ void CInputDB::ChangeEmpirePriv(const char* c_pData)
}
/**
* @version 05/06/08 Bang2ni -
* @version 05/06/08 Bang2ni -
*/
void CInputDB::ChangeGuildPriv(const char* c_pData)
{
@ -2101,7 +2101,7 @@ void CInputDB::ReloadAdmin(const char * c_pData )
////////////////////////////////////////////////////////////////////
// Analyze
// @version 05/06/10 Bang2ni - 아이템 가격정보 리스트 패킷(HEADER_DG_MYSHOP_PRICELIST_RES) 처리루틴 추가.
// @version 05/06/10 Bang2ni - 아이템 가격정보 리스트 패킷(HEADER_DG_MYSHOP_PRICELIST_RES) 처리루틴 추가.
////////////////////////////////////////////////////////////////////
int CInputDB::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
{
@ -2450,7 +2450,7 @@ int CInputDB::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
case HEADER_DG_NEED_LOGIN_LOG:
DetailLog( (TPacketNeedLoginLogInfo*) c_pData );
break;
// 독일 선물 기능 테스트
// 독일 선물 기능 테스트
case HEADER_DG_ITEMAWARD_INFORMER:
ItemAwardInformer((TPacketItemAwardInfromer*) c_pData);
break;
@ -2618,7 +2618,7 @@ void CInputDB::DetailLog(const TPacketNeedLoginLogInfo* info)
void CInputDB::ItemAwardInformer(TPacketItemAwardInfromer *data)
{
LPDESC d = DESC_MANAGER::instance().FindByLoginName(data->login); //login정보
LPDESC d = DESC_MANAGER::instance().FindByLoginName(data->login); //login정보
if(d == NULL)
return;
@ -2627,12 +2627,12 @@ void CInputDB::ItemAwardInformer(TPacketItemAwardInfromer *data)
if (d->GetCharacter())
{
LPCHARACTER ch = d->GetCharacter();
ch->SetItemAward_vnum(data->vnum); // ch 에 임시 저장해놨다가 QuestLoad 함수에서 처리
ch->SetItemAward_vnum(data->vnum); // ch 에 임시 저장해놨다가 QuestLoad 함수에서 처리
ch->SetItemAward_cmd(data->command);
if(d->IsPhase(PHASE_GAME)) //게임페이즈일때
if(d->IsPhase(PHASE_GAME)) //게임페이즈일때
{
quest::CQuestManager::instance().ItemInformer(ch->GetPlayerID(),ch->GetItemAward_vnum()); //questmanager 호출
quest::CQuestManager::instance().ItemInformer(ch->GetPlayerID(),ch->GetItemAward_vnum()); //questmanager 호출
}
}
}

View File

@ -68,13 +68,13 @@ static bool FN_is_battle_zone(LPCHARACTER ch)
{
switch (ch->GetMapIndex())
{
case 1: // 신수 1차 마을
case 2: // 신수 2차 마을
case 21: // 천조 1차 마을
case 23: // 천조 2차 마을
case 41: // 진노 1차 마을
case 43: // 진노 2차 마을
case 113: // OX 맵
case 1: // 신수 1차 마을
case 2: // 신수 2차 마을
case 21: // 천조 1차 마을
case 23: // 천조 2차 마을
case 41: // 진노 1차 마을
case 43: // 진노 2차 마을
case 113: // OX 맵
return false;
}
@ -373,7 +373,7 @@ bool RaceToJob(unsigned race, unsigned* ret_job)
return true;
}
// 신규 캐릭터 지원
// 신규 캐릭터 지원
bool NewPlayerTable2(TPlayerTable * table, const char * name, BYTE race, BYTE shape, BYTE bEmpire)
{
if (race >= MAIN_RACE_MAX_NUM)
@ -397,7 +397,7 @@ bool NewPlayerTable2(TPlayerTable * table, const char * name, BYTE race, BYTE sh
strlcpy(table->name, name, sizeof(table->name));
table->level = 1;
table->job = race; // 직업대신 종족을 넣는다
table->job = race; // 직업대신 종족을 넣는다
table->voice = 0;
table->part_base = shape;
@ -443,7 +443,7 @@ void CInputLogin::CharacterCreate(LPDESC d, const char * data)
return;
}
// 사용할 수 없는 이름이거나, 잘못된 평상복이면 생설 실패
// 사용할 수 없는 이름이거나, 잘못된 평상복이면 생설 실패
if (!check_name(pinfo->name) || pinfo->shape > 1)
{
if (LC_IsCanada() == true)
@ -573,7 +573,7 @@ void CInputLogin::Entergame(LPDESC d, const char * data)
CGuildManager::instance().LoginMember(ch);
// 캐릭터를 맵에 추가
// 캐릭터를 맵에 추가
ch->Show(ch->GetMapIndex(), pos.x, pos.y, pos.z);
SECTREE_MANAGER::instance().SendNPCPosition(ch);
@ -581,8 +581,8 @@ void CInputLogin::Entergame(LPDESC d, const char * data)
d->SetPhase(PHASE_GAME);
if(ch->GetItemAward_cmd()) //게임페이즈 들어가면
quest::CQuestManager::instance().ItemInformer(ch->GetPlayerID(),ch->GetItemAward_vnum()); //questmanager 호출
if(ch->GetItemAward_cmd()) //게임페이즈 들어가면
quest::CQuestManager::instance().ItemInformer(ch->GetPlayerID(),ch->GetItemAward_vnum()); //questmanager 호출
SPDLOG_DEBUG("ENTERGAME: {} {}x{}x{} {} map_index {}",
ch->GetName(), ch->GetX(), ch->GetY(), ch->GetZ(), d->GetHostName(), ch->GetMapIndex());
@ -592,10 +592,10 @@ void CInputLogin::Entergame(LPDESC d, const char * data)
ch->EnterHorse();
}
// 플레이시간 레코딩 시작
// 플레이시간 레코딩 시작
ch->ResetPlayTime();
// 자동 저장 이벤트 추가
// 자동 저장 이벤트 추가
ch->StartSaveEvent();
ch->StartRecoveryEvent();
ch->StartCheckSpeedHackEvent();
@ -751,10 +751,10 @@ void CInputLogin::Entergame(LPDESC d, const char * data)
}
else if (ch->GetMapIndex() == 113)
{
// ox 이벤트 맵
// ox 이벤트 맵
if (COXEventManager::instance().Enter(ch) == false)
{
// ox 맵 진입 허가가 나지 않음. 플레이어면 마을로 보내자
// ox 맵 진입 허가가 나지 않음. 플레이어면 마을로 보내자
if (ch->GetGMLevel() == GM_PLAYER)
ch->WarpSet(EMPIRE_START_X(ch->GetEmpire()), EMPIRE_START_Y(ch->GetEmpire()));
}
@ -769,8 +769,8 @@ void CInputLogin::Entergame(LPDESC d, const char * data)
}
}
// 청소년 보호
if (g_TeenDesc) // RawPacket 사용 금지
// 청소년 보호
if (g_TeenDesc) // RawPacket 사용 금지
{
TPacketGTLogin p;
@ -790,7 +790,7 @@ void CInputLogin::Entergame(LPDESC d, const char * data)
db_clientdesc->DBPacket(HEADER_GD_REQ_HORSE_NAME, 0, &pid, sizeof(DWORD));
}
// 중립맵에 들어갔을때 안내하기
// 중립맵에 들어갔을때 안내하기
if (g_noticeBattleZone)
{
if (FN_is_battle_zone(ch))
@ -850,13 +850,13 @@ int CInputLogin::GuildSymbolUpload(LPDESC d, const char* c_pData, size_t uiBytes
if (iSymbolSize <= 0 || iSymbolSize > 64 * 1024)
{
// 64k 보다 큰 길드 심볼은 올릴수없다
// 접속을 끊고 무시
// 64k 보다 큰 길드 심볼은 올릴수없다
// 접속을 끊고 무시
d->SetPhase(PHASE_CLOSE);
return 0;
}
// 땅을 소유하지 않은 길드인 경우.
// 땅을 소유하지 않은 길드인 경우.
if (!test_server)
if (!building::CManager::instance().FindLandByGuild(p->guild_id))
{
@ -972,7 +972,7 @@ void CInputLogin::GuildMarkCRCList(LPDESC d, const char* c_pData)
CGuildMarkManager::instance().GetDiffBlocks(pCG->imgIdx, pCG->crclist, mapDiffBlocks);
DWORD blockCount = 0;
TEMP_BUFFER buf(1024 * 1024); // 1M 버퍼
TEMP_BUFFER buf(1024 * 1024); // 1M 버퍼
for (itertype(mapDiffBlocks) it = mapDiffBlocks.begin(); it != mapDiffBlocks.end(); ++it)
{

View File

@ -45,7 +45,7 @@ extern int g_nPortalLimitTime;
static int __deposit_limit()
{
return (1000*10000); // 1천만
return (1000*10000); // 1천만
}
void SendBlockChatInfo(LPCHARACTER ch, int sec)
@ -181,7 +181,7 @@ int GetTextTag(const char * src, int maxLen, int & tagLen, std::string & extraIn
const char * cur = ++src;
if (*cur == '|') // ||는 |로 표시한다.
if (*cur == '|') // ||는 |로 표시한다.
{
tagLen = 2;
return TEXT_TAG_TAG;
@ -191,7 +191,7 @@ int GetTextTag(const char * src, int maxLen, int & tagLen, std::string & extraIn
tagLen = 2;
return TEXT_TAG_COLOR;
}
else if (*cur == 'H') // hyperlink |Hitem:10000:0:0:0:0|h[이름]|h
else if (*cur == 'H') // hyperlink |Hitem:10000:0:0:0:0|h[이름]|h
{
tagLen = 2;
return TEXT_TAG_HYPERLINK_START;
@ -229,12 +229,12 @@ void GetTextTagInfo(const char * src, int src_len, int & hyperlinks, bool & colo
int ProcessTextTag(LPCHARACTER ch, const char * c_pszText, size_t len)
{
//2012.05.17 김용욱
//0 : 정상적으로 사용
//1 : 금강경 부족
//2 : 금강경이 있으나, 개인상점에서 사용중
//3 : 교환중
//4 : 에러
//2012.05.17 김용욱
//0 : 정상적으로 사용
//1 : 금강경 부족
//2 : 금강경이 있으나, 개인상점에서 사용중
//3 : 교환중
//4 : 에러
int hyperlinks;
bool colored;
@ -419,18 +419,18 @@ int CInputMain::Whisper(LPCHARACTER ch, const char * data, size_t uiBytes)
if (g_bEmpireWhisper)
if (!ch->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
if (!(pkChr && pkChr->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE)))
if (bOpponentEmpire != ch->GetEmpire() && ch->GetEmpire() && bOpponentEmpire // 서로 제국이 다르면서
&& ch->GetGMLevel() == GM_PLAYER && gm_get_level(pinfo->szNameTo) == GM_PLAYER) // 둘다 일반 플레이어이면
// 이름 밖에 모르니 gm_get_level 함수를 사용
if (bOpponentEmpire != ch->GetEmpire() && ch->GetEmpire() && bOpponentEmpire // 서로 제국이 다르면서
&& ch->GetGMLevel() == GM_PLAYER && gm_get_level(pinfo->szNameTo) == GM_PLAYER) // 둘다 일반 플레이어이면
// 이름 밖에 모르니 gm_get_level 함수를 사용
{
if (!pkChr)
{
// 다른 서버에 있으니 제국 표시만 한다. bType의 상위 4비트를 Empire번호로 사용한다.
// 다른 서버에 있으니 제국 표시만 한다. bType의 상위 4비트를 Empire번호로 사용한다.
bType = ch->GetEmpire() << 4;
}
else
{
ConvertEmpireText(ch->GetEmpire(), buf, buflen, 10 + 2 * pkChr->GetSkillPower(SKILL_LANGUAGE1 + ch->GetEmpire() - 1)/*변환확률*/);
ConvertEmpireText(ch->GetEmpire(), buf, buflen, 10 + 2 * pkChr->GetSkillPower(SKILL_LANGUAGE1 + ch->GetEmpire() - 1)/*변환확률*/);
}
}
@ -445,7 +445,7 @@ int CInputMain::Whisper(LPCHARACTER ch, const char * data, size_t uiBytes)
{
char buf[128];
int len;
if (3==processReturn) //교환중
if (3==processReturn) //교환중
len = snprintf(buf, sizeof(buf), LC_TEXT("\xB4\xD9\xB8\xA5 \xB0\xC5\xB7\xA1\xC1\xDF(\xC3\xA2\xB0\xED,\xB1\xB3\xC8\xAF,\xBB\xF3\xC1\xA1)\xBF\xA1\xB4\xC2 \xB0\xB3\xC0\xCE\xBB\xF3\xC1\xA1\xC0\xBB \xBB\xE7\xBF\xEB\xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."), pTable->szLocaleName);
else
len = snprintf(buf, sizeof(buf), LC_TEXT("%s\xC0\xCC \xC7\xCA\xBF\xE4\xC7\xD5\xB4\xCF\xB4\xD9."), pTable->szLocaleName);
@ -454,7 +454,7 @@ int CInputMain::Whisper(LPCHARACTER ch, const char * data, size_t uiBytes)
if (len < 0 || len >= (int) sizeof(buf))
len = sizeof(buf) - 1;
++len; // \0 문자 포함
++len; // \0 문자 포함
TPacketGCWhisper pack;
@ -470,7 +470,7 @@ int CInputMain::Whisper(LPCHARACTER ch, const char * data, size_t uiBytes)
}
}
// 릴래이 상태일 수 있으므로 릴래이를 풀어준다.
// 릴래이 상태일 수 있으므로 릴래이를 풀어준다.
pkDesc->SetRelay("");
return (iExtraLen);
}
@ -487,8 +487,8 @@ int CInputMain::Whisper(LPCHARACTER ch, const char * data, size_t uiBytes)
pack.bType = bType;
strlcpy(pack.szNameFrom, ch->GetName(), sizeof(pack.szNameFrom));
// desc->BufferedPacket을 하지 않고 버퍼에 써야하는 이유는
// P2P relay되어 패킷이 캡슐화 될 수 있기 때문이다.
// desc->BufferedPacket을 하지 않고 버퍼에 써야하는 이유는
// P2P relay되어 패킷이 캡슐화 될 수 있기 때문이다.
TEMP_BUFFER tmpbuf;
tmpbuf.write(&pack, sizeof(pack));
@ -563,7 +563,7 @@ struct FEmpireChatPacket
}
else
{
// 사람마다 스킬레벨이 다르니 매번 해야합니다
// 사람마다 스킬레벨이 다르니 매번 해야합니다
strlcpy(converted_msg, orig_msg, sizeof(converted_msg));
ConvertEmpireText(bEmpire, converted_msg + namelen, sizeof(converted_msg) - namelen, 10 + 2 * d->GetCharacter()->GetSkillPower(SKILL_LANGUAGE1 + bEmpire - 1));
@ -595,17 +595,17 @@ struct FYmirChatPacket
m_iMapIndex(iMapIndex), m_bEmpire(empire),
m_ring(ring)
{
m_len_orig_msg = snprintf(m_orig_msg, sizeof(m_orig_msg), "%s : %s", m_szName, m_szChat) + 1; // 널 문자 포함
m_len_orig_msg = snprintf(m_orig_msg, sizeof(m_orig_msg), "%s : %s", m_szName, m_szChat) + 1; // 널 문자 포함
if (m_len_orig_msg < 0 || m_len_orig_msg >= (int) sizeof(m_orig_msg))
m_len_orig_msg = sizeof(m_orig_msg) - 1;
m_len_conv_msg = snprintf(m_conv_msg, sizeof(m_conv_msg), "??? : %s", m_szChat) + 1; // 널 문자 미포함
m_len_conv_msg = snprintf(m_conv_msg, sizeof(m_conv_msg), "??? : %s", m_szChat) + 1; // 널 문자 미포함
if (m_len_conv_msg < 0 || m_len_conv_msg >= (int) sizeof(m_conv_msg))
m_len_conv_msg = sizeof(m_conv_msg) - 1;
ConvertEmpireText(m_bEmpire, m_conv_msg + 6, m_len_conv_msg - 6, 10); // 6은 "??? : "의 길이
ConvertEmpireText(m_bEmpire, m_conv_msg + 6, m_len_conv_msg - 6, 10); // 6은 "??? : "의 길이
}
void operator() (LPDESC d)
@ -673,7 +673,7 @@ int CInputMain::Chat(LPCHARACTER ch, const char * data, size_t uiBytes)
return iExtraLen;
}
// 채팅 금지 Affect 처리
// 채팅 금지 Affect 처리
const CAffect* pAffect = ch->FindAffect(AFFECT_BLOCK_CHAT);
if (pAffect != NULL)
@ -710,7 +710,7 @@ int CInputMain::Chat(LPCHARACTER ch, const char * data, size_t uiBytes)
if (NULL != pTable)
{
if (3==processReturn) //교환중
if (3==processReturn) //교환중
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB4\xD9\xB8\xA5 \xB0\xC5\xB7\xA1\xC1\xDF(\xC3\xA2\xB0\xED,\xB1\xB3\xC8\xAF,\xBB\xF3\xC1\xA1)\xBF\xA1\xB4\xC2 \xB0\xB3\xC0\xCE\xBB\xF3\xC1\xA1\xC0\xBB \xBB\xE7\xBF\xEB\xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."), pTable->szLocaleName);
else
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s\xC0\xCC \xC7\xCA\xBF\xE4\xC7\xD5\xB4\xCF\xB4\xD9."), pTable->szLocaleName);
@ -843,7 +843,7 @@ void CInputMain::ItemDrop(LPCHARACTER ch, const char * data)
if (!ch)
return;
// 엘크가 0보다 크면 엘크를 버리는 것 이다.
// 엘크가 0보다 크면 엘크를 버리는 것 이다.
if (pinfo->gold > 0)
ch->DropGold(pinfo->gold);
else
@ -859,7 +859,7 @@ void CInputMain::ItemDrop2(LPCHARACTER ch, const char * data)
TPacketCGItemDrop2 * pinfo = (TPacketCGItemDrop2 *) data;
// 엘크가 0보다 크면 엘크를 버리는 것 이다.
// 엘크가 0보다 크면 엘크를 버리는 것 이다.
if (!ch)
return;
@ -945,7 +945,7 @@ int CInputMain::Messenger(LPCHARACTER ch, const char* c_pData, size_t uiBytes)
return sizeof(TPacketCGMessengerAddByVID);
}
if (ch->GetDesc() == d) // 자신은 추가할 수 없다.
if (ch->GetDesc() == d) // 자신은 추가할 수 없다.
return sizeof(TPacketCGMessengerAddByVID);
MessengerManager::instance().RequestToAdd(ch, ch_companion);
@ -973,7 +973,7 @@ int CInputMain::Messenger(LPCHARACTER ch, const char* c_pData, size_t uiBytes)
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s \xB4\xD4\xC0\xBA \xC1\xA2\xBC\xD3\xB5\xC7 \xC0\xD6\xC1\xF6 \xBE\xCA\xBD\xC0\xB4\xCF\xB4\xD9."), name);
else
{
if (tch == ch) // 자신은 추가할 수 없다.
if (tch == ch) // 자신은 추가할 수 없다.
return CHARACTER_NAME_MAX_LEN;
if (tch->IsBlockMode(BLOCK_MESSENGER_INVITE) == true)
@ -982,7 +982,7 @@ int CInputMain::Messenger(LPCHARACTER ch, const char* c_pData, size_t uiBytes)
}
else
{
// 메신저가 캐릭터단위가 되면서 변경
// 메신저가 캐릭터단위가 되면서 변경
MessengerManager::instance().RequestToAdd(ch, tch);
//MessengerManager::instance().AddToList(ch->GetName(), tch->GetName());
}
@ -1268,7 +1268,7 @@ static const int ComboSequenceBySkillLevel[3][8] =
DWORD ClacValidComboInterval( LPCHARACTER ch, BYTE bArg )
{
int nInterval = 300;
float fAdjustNum = 1.5f; // 일반 유저가 speed hack 에 걸리는 것을 막기 위해. 2013.09.10 CYH
float fAdjustNum = 1.5f; // 일반 유저가 speed hack 에 걸리는 것을 막기 위해. 2013.09.10 CYH
if( !ch )
{
@ -1299,17 +1299,17 @@ DWORD ClacValidComboInterval( LPCHARACTER ch, BYTE bArg )
bool CheckComboHack(LPCHARACTER ch, BYTE bArg, DWORD dwTime, bool CheckSpeedHack)
{
// 죽거나 기절 상태에서는 공격할 수 없으므로, skip한다.
// 이렇게 하지 말고, CHRACTER::CanMove()에
// 죽거나 기절 상태에서는 공격할 수 없으므로, skip한다.
// 이렇게 하지 말고, CHRACTER::CanMove()에
// if (IsStun() || IsDead()) return false;
// 를 추가하는게 맞다고 생각하나,
// 이미 다른 부분에서 CanMove()는 IsStun(), IsDead()과
// 독립적으로 체크하고 있기 때문에 수정에 의한 영향을
// 최소화하기 위해 이렇게 땜빵 코드를 써놓는다.
// 를 추가하는게 맞다고 생각하나,
// 이미 다른 부분에서 CanMove()는 IsStun(), IsDead()과
// 독립적으로 체크하고 있기 때문에 수정에 의한 영향을
// 최소화하기 위해 이렇게 땜빵 코드를 써놓는다.
if (ch->IsStun() || ch->IsDead())
return false;
int ComboInterval = dwTime - ch->GetLastComboTime();
int HackScalar = 0; // 기본 스칼라 단위 1
int HackScalar = 0; // 기본 스칼라 단위 1
// [2013 09 11 CYH] debugging log
/*SPDLOG_DEBUG("COMBO_TEST_LOG: {} arg:{} interval:{} valid:{} atkspd:{} riding:{}",
@ -1324,18 +1324,18 @@ bool CheckComboHack(LPCHARACTER ch, BYTE bArg, DWORD dwTime, bool CheckSpeedHack
SPDLOG_DEBUG("COMBO: {} arg:{} seq:{} delta:{} checkspeedhack:{}",
ch->GetName(), bArg, ch->GetComboSequence(), ComboInterval - ch->GetValidComboInterval(), CheckSpeedHack);
#endif
// bArg 14 ~ 21번 까지 총 8콤보 가능
// 1. 첫 콤보(14)는 일정 시간 이후에 반복 가능
// 2. 15 ~ 21번은 반복 불가능
// 3. 차례대로 증가한다.
// bArg 14 ~ 21번 까지 총 8콤보 가능
// 1. 첫 콤보(14)는 일정 시간 이후에 반복 가능
// 2. 15 ~ 21번은 반복 불가능
// 3. 차례대로 증가한다.
if (bArg == 14)
{
if (CheckSpeedHack && ComboInterval > 0 && ComboInterval < ch->GetValidComboInterval() - COMBO_HACK_ALLOWABLE_MS)
{
// FIXME 첫번째 콤보는 이상하게 빨리 올 수가 있어서 300으로 나눔 -_-;
// 다수의 몬스터에 의해 다운되는 상황에서 공격을 하면
// 첫번째 콤보가 매우 적은 인터벌로 들어오는 상황 발생.
// 이로 인해 콤보핵으로 튕기는 경우가 있어 다음 코드 비 활성화.
// FIXME 첫번째 콤보는 이상하게 빨리 올 수가 있어서 300으로 나눔 -_-;
// 다수의 몬스터에 의해 다운되는 상황에서 공격을 하면
// 첫번째 콤보가 매우 적은 인터벌로 들어오는 상황 발생.
// 이로 인해 콤보핵으로 튕기는 경우가 있어 다음 코드 비 활성화.
//HackScalar = 1 + (ch->GetValidComboInterval() - ComboInterval) / 300;
//SPDLOG_WARN("COMBO_HACK: 2 {} arg:{} interval:{} valid:{} atkspd:{} riding:{}",
@ -1357,13 +1357,13 @@ bool CheckComboHack(LPCHARACTER ch, BYTE bArg, DWORD dwTime, bool CheckSpeedHack
{
int idx = std::min<int>(2, ch->GetComboIndex());
if (ch->GetComboSequence() > 5) // 현재 6콤보 이상은 없다.
if (ch->GetComboSequence() > 5) // 현재 6콤보 이상은 없다.
{
HackScalar = 1;
ch->SetValidComboInterval(300);
SPDLOG_WARN("COMBO_HACK: 5 {} combo_seq:{}", ch->GetName(), ch->GetComboSequence());
}
// 자객 쌍수 콤보 예외처리
// 자객 쌍수 콤보 예외처리
else if (bArg == 21 &&
idx == 2 &&
ch->GetComboSequence() == 5 &&
@ -1398,7 +1398,7 @@ bool CheckComboHack(LPCHARACTER ch, BYTE bArg, DWORD dwTime, bool CheckSpeedHack
ch->IsRiding() ? "yes" : "no");
}
// 말을 탔을 때는 15번 ~ 16번을 반복한다
// 말을 탔을 때는 15번 ~ 16번을 반복한다
//if (ch->IsHorseRiding())
if (ch->IsRiding())
ch->SetComboSequence(ch->GetComboSequence() == 1 ? 2 : 1);
@ -1411,13 +1411,13 @@ bool CheckComboHack(LPCHARACTER ch, BYTE bArg, DWORD dwTime, bool CheckSpeedHack
ch->SetLastComboTime(dwTime);
}
}
else if (bArg == 13) // 기본 공격 (둔갑(Polymorph)했을 때 온다)
else if (bArg == 13) // 기본 공격 (둔갑(Polymorph)했을 때 온다)
{
if (CheckSpeedHack && ComboInterval > 0 && ComboInterval < ch->GetValidComboInterval() - COMBO_HACK_ALLOWABLE_MS)
{
// 다수의 몬스터에 의해 다운되는 상황에서 공격을 하면
// 첫번째 콤보가 매우 적은 인터벌로 들어오는 상황 발생.
// 이로 인해 콤보핵으로 튕기는 경우가 있어 다음 코드 비 활성화.
// 다수의 몬스터에 의해 다운되는 상황에서 공격을 하면
// 첫번째 콤보가 매우 적은 인터벌로 들어오는 상황 발생.
// 이로 인해 콤보핵으로 튕기는 경우가 있어 다음 코드 비 활성화.
//HackScalar = 1 + (ch->GetValidComboInterval() - ComboInterval) / 100;
//SPDLOG_WARN("COMBO_HACK: 6 {} arg:{} interval:{} valid:{} atkspd:{}",
@ -1440,8 +1440,8 @@ bool CheckComboHack(LPCHARACTER ch, BYTE bArg, DWORD dwTime, bool CheckSpeedHack
SPDLOG_ERROR("cannot find motion by race {}", ch->GetRaceNum());
else
{
// 정상적 계산이라면 1000.f를 곱해야 하지만 클라이언트가 애니메이션 속도의 90%에서
// 다음 애니메이션 블렌딩을 허용하므로 900.f를 곱한다.
// 정상적 계산이라면 1000.f를 곱해야 하지만 클라이언트가 애니메이션 속도의 90%에서
// 다음 애니메이션 블렌딩을 허용하므로 900.f를 곱한다.
int k = (int) (pkMotion->GetDuration() / ((float) ch->GetPoint(POINT_ATT_SPEED) / 100.f) * 900.f);
ch->SetValidComboInterval(k);
ch->SetLastComboTime(dwTime);
@ -1458,32 +1458,32 @@ bool CheckComboHack(LPCHARACTER ch, BYTE bArg, DWORD dwTime, bool CheckSpeedHack
}
else
{
// 말이 안되는 콤보가 왔다 해커일 가능성?
// 말이 안되는 콤보가 왔다 해커일 가능성?
//if (ch->GetDesc()->DelayedDisconnect(Random::get(2, 9)))
//{
// LogManager::instance().HackLog("Hacker", ch);
// SPDLOG_WARN("HACKER: {} arg {}", ch->GetName(), bArg);
//}
// 위 코드로 인해, 폴리모프를 푸는 중에 공격 하면,
// 가끔 핵으로 인식하는 경우가 있다.
// 위 코드로 인해, 폴리모프를 푸는 중에 공격 하면,
// 가끔 핵으로 인식하는 경우가 있다.
// 자세히 말혀면,
// 서버에서 poly 0를 처리했지만,
// 클라에서 그 패킷을 받기 전에, 몹을 공격. <- 즉, 몹인 상태에서 공격.
// 자세히 말혀면,
// 서버에서 poly 0를 처리했지만,
// 클라에서 그 패킷을 받기 전에, 몹을 공격. <- 즉, 몹인 상태에서 공격.
//
// 그러면 클라에서는 서버에 몹 상태로 공격했다는 커맨드를 보내고 (arg == 13)
// 그러면 클라에서는 서버에 몹 상태로 공격했다는 커맨드를 보내고 (arg == 13)
//
// 서버에서는 race는 인간인데 공격형태는 몹인 놈이다! 라고 하여 핵체크를 했다.
// 서버에서는 race는 인간인데 공격형태는 몹인 놈이다! 라고 하여 핵체크를 했다.
// 사실 공격 패턴에 대한 것은 클라이언트에서 판단해서 보낼 것이 아니라,
// 서버에서 판단해야 할 것인데... 왜 이렇게 해놨을까...
// 사실 공격 패턴에 대한 것은 클라이언트에서 판단해서 보낼 것이 아니라,
// 서버에서 판단해야 할 것인데... 왜 이렇게 해놨을까...
// by rtsummit
}
}
else
{
// 말이 안되는 콤보가 왔다 해커일 가능성?
// 말이 안되는 콤보가 왔다 해커일 가능성?
if (ch->GetDesc()->DelayedDisconnect(Random::get(2, 9)))
{
LogManager::instance().HackLog("Hacker", ch);
@ -1496,7 +1496,7 @@ bool CheckComboHack(LPCHARACTER ch, BYTE bArg, DWORD dwTime, bool CheckSpeedHack
if (HackScalar)
{
// 말에 타거나 내렸을 때 1.5초간 공격은 핵으로 간주하지 않되 공격력은 없게 하는 처리
// 말에 타거나 내렸을 때 1.5초간 공격은 핵으로 간주하지 않되 공격력은 없게 하는 처리
if (get_dword_time() - ch->GetLastMountTime() > 1500)
ch->IncreaseComboHackCount(1 + HackScalar);
@ -1531,9 +1531,9 @@ void CInputMain::Move(LPCHARACTER ch, const char * data)
// FUNC_SKILL = 0x80,
//};
// 텔레포트 핵 체크
// 텔레포트 핵 체크
// if (!test_server) //2012.05.15 김용욱 : 테섭에서 (무적상태로) 다수 몬스터 상대로 다운되면서 공격시 콤보핵으로 죽는 문제가 있었다.
// if (!test_server) //2012.05.15 김용욱 : 테섭에서 (무적상태로) 다수 몬스터 상대로 다운되면서 공격시 콤보핵으로 죽는 문제가 있었다.
{
const float fDist = DISTANCE_SQRT((ch->GetX() - pinfo->lX) / 100, (ch->GetY() - pinfo->lY) / 100);
@ -1544,7 +1544,7 @@ void CInputMain::Move(LPCHARACTER ch, const char * data)
const PIXEL_POSITION & warpPos = ch->GetWarpPosition();
if (warpPos.x == 0 && warpPos.y == 0)
LogManager::instance().HackLog("Teleport", ch); // 부정확할 수 있음
LogManager::instance().HackLog("Teleport", ch); // 부정확할 수 있음
}
SPDLOG_WARN("MOVE: {} trying to move too far (dist: {:.1f}m) Riding({})", ch->GetName(), fDist, ch->IsRiding());
@ -1555,10 +1555,10 @@ void CInputMain::Move(LPCHARACTER ch, const char * data)
}
//
// 스피드핵(SPEEDHACK) Check
// 스피드핵(SPEEDHACK) Check
//
DWORD dwCurTime = get_dword_time();
// 시간을 Sync하고 7초 후 부터 검사한다. (20090702 이전엔 5초였음)
// 시간을 Sync하고 7초 후 부터 검사한다. (20090702 이전엔 5초였음)
bool CheckSpeedHack = (false == ch->GetDesc()->IsHandshaking() && dwCurTime - ch->GetDesc()->GetClientTime() > 7000);
if (CheckSpeedHack)
@ -1568,13 +1568,13 @@ void CInputMain::Move(LPCHARACTER ch, const char * data)
iDelta = (int) (dwCurTime - pinfo->dwTime);
// 시간이 늦게간다. 일단 로그만 해둔다. 진짜 이런 사람들이 많은지 체크해야함. TODO
// 시간이 늦게간다. 일단 로그만 해둔다. 진짜 이런 사람들이 많은지 체크해야함. TODO
if (iDelta >= 30000)
{
SPDLOG_WARN("SPEEDHACK: slow timer name {} delta {}", ch->GetName(), iDelta);
ch->GetDesc()->DelayedDisconnect(3);
}
// 1초에 20msec 빨리 가는거 까지는 이해한다.
// 1초에 20msec 빨리 가는거 까지는 이해한다.
else if (iDelta < -(iServerDelta / 50))
{
SPDLOG_WARN("SPEEDHACK: DETECTED! {} (delta {} {})", ch->GetName(), iDelta, iServerDelta);
@ -1583,11 +1583,11 @@ void CInputMain::Move(LPCHARACTER ch, const char * data)
}
//
// 콤보핵 및 스피드핵 체크
// 콤보핵 및 스피드핵 체크
//
if (pinfo->bFunc == FUNC_COMBO && g_bCheckMultiHack)
{
CheckComboHack(ch, pinfo->bArg, pinfo->dwTime, CheckSpeedHack); // 콤보 체크
CheckComboHack(ch, pinfo->bArg, pinfo->dwTime, CheckSpeedHack); // 콤보 체크
}
}
@ -1596,7 +1596,7 @@ void CInputMain::Move(LPCHARACTER ch, const char * data)
if (ch->GetLimitPoint(POINT_MOV_SPEED) == 0)
return;
ch->SetRotation(pinfo->bRot * 5); // 중복 코드
ch->SetRotation(pinfo->bRot * 5); // 중복 코드
ch->ResetStopTime(); // ""
ch->Goto(pinfo->lX, pinfo->lY);
@ -1635,7 +1635,7 @@ void CInputMain::Move(LPCHARACTER ch, const char * data)
ch->OnMove();
}
ch->SetRotation(pinfo->bRot * 5); // 중복 코드
ch->SetRotation(pinfo->bRot * 5); // 중복 코드
ch->ResetStopTime(); // ""
ch->Move(pinfo->lX, pinfo->lY);
@ -1657,13 +1657,13 @@ void CInputMain::Move(LPCHARACTER ch, const char * data)
ch->PacketAround(&pack, sizeof(TPacketGCMove), ch);
/*
if (pinfo->dwTime == 10653691) // 디버거 발견
if (pinfo->dwTime == 10653691) // 디버거 발견
{
if (ch->GetDesc()->DelayedDisconnect(Random::get(15, 30)))
LogManager::instance().HackLog("Debugger", ch);
}
else if (pinfo->dwTime == 10653971) // Softice 발견
else if (pinfo->dwTime == 10653971) // Softice 발견
{
if (ch->GetDesc()->DelayedDisconnect(Random::get(15, 30)))
LogManager::instance().HackLog("Softice", ch);
@ -1839,20 +1839,20 @@ int CInputMain::SyncPosition(LPCHARACTER ch, const char * c_pcData, size_t uiByt
continue;
}
// 소유권 검사
// 소유권 검사
if (!victim->SetSyncOwner(ch))
continue;
const float fDistWithSyncOwner = DISTANCE_SQRT( (victim->GetX() - ch->GetX()) / 100, (victim->GetY() - ch->GetY()) / 100 );
static const float fLimitDistWithSyncOwner = 2500.f + 1000.f;
// victim과의 거리가 2500 + a 이상이면 핵으로 간주.
// 거리 참조 : 클라이언트의 __GetSkillTargetRange, __GetBowRange 함수
// 2500 : 스킬 proto에서 가장 사거리가 긴 스킬의 사거리, 또는 활의 사거리
// a = POINT_BOW_DISTANCE 값... 인데 실제로 사용하는 값인지는 잘 모르겠음. 아이템이나 포션, 스킬, 퀘스트에는 없는데...
// 그래도 혹시나 하는 마음에 버퍼로 사용할 겸해서 1000.f 로 둠...
// victim과의 거리가 2500 + a 이상이면 핵으로 간주.
// 거리 참조 : 클라이언트의 __GetSkillTargetRange, __GetBowRange 함수
// 2500 : 스킬 proto에서 가장 사거리가 긴 스킬의 사거리, 또는 활의 사거리
// a = POINT_BOW_DISTANCE 값... 인데 실제로 사용하는 값인지는 잘 모르겠음. 아이템이나 포션, 스킬, 퀘스트에는 없는데...
// 그래도 혹시나 하는 마음에 버퍼로 사용할 겸해서 1000.f 로 둠...
if (fDistWithSyncOwner > fLimitDistWithSyncOwner)
{
// g_iSyncHackLimitCount번 까지는 봐줌.
// g_iSyncHackLimitCount번 까지는 봐줌.
if (ch->GetSyncHackCount() < g_iSyncHackLimitCount)
{
ch->SetSyncHackCount(ch->GetSyncHackCount() + 1);
@ -1877,11 +1877,11 @@ int CInputMain::SyncPosition(LPCHARACTER ch, const char * c_pcData, size_t uiByt
const timeval &tvLastSyncTime = victim->GetLastSyncTime();
timeval *tvDiff = timediff(&tvCurTime, &tvLastSyncTime);
// SyncPosition을 악용하여 타유저를 이상한 곳으로 보내는 핵 방어하기 위하여,
// 같은 유저를 g_lValidSyncInterval ms 이내에 다시 SyncPosition하려고 하면 핵으로 간주.
// SyncPosition을 악용하여 타유저를 이상한 곳으로 보내는 핵 방어하기 위하여,
// 같은 유저를 g_lValidSyncInterval ms 이내에 다시 SyncPosition하려고 하면 핵으로 간주.
if (tvDiff->tv_sec == 0 && tvDiff->tv_usec < g_lValidSyncInterval)
{
// g_iSyncHackLimitCount번 까지는 봐줌.
// g_iSyncHackLimitCount번 까지는 봐줌.
if (ch->GetSyncHackCount() < g_iSyncHackLimitCount)
{
ch->SetSyncHackCount(ch->GetSyncHackCount() + 1);
@ -1968,11 +1968,11 @@ void CInputMain::ScriptAnswer(LPCHARACTER ch, const void* c_pData)
TPacketCGScriptAnswer * p = (TPacketCGScriptAnswer *) c_pData;
SPDLOG_DEBUG("QUEST ScriptAnswer pid {} answer {}", ch->GetPlayerID(), p->answer);
if (p->answer > 250) // 다음 버튼에 대한 응답으로 온 패킷인 경우
if (p->answer > 250) // 다음 버튼에 대한 응답으로 온 패킷인 경우
{
quest::CQuestManager::Instance().Resume(ch->GetPlayerID());
}
else // 선택 버튼을 골라서 온 패킷인 경우
else // 선택 버튼을 골라서 온 패킷인 경우
{
quest::CQuestManager::Instance().Select(ch->GetPlayerID(), p->answer);
}
@ -2115,9 +2115,9 @@ void CInputMain::SafeboxCheckout(LPCHARACTER ch, const char * c_pData, bool bMal
if (!ch->IsEmptyItemGrid(p->ItemPos, pkItem->GetSize()))
return;
// 아이템 몰에서 인벤으로 옮기는 부분에서 용혼석 특수 처리
// (몰에서 만드는 아이템은 item_proto에 정의된대로 속성이 붙기 때문에,
// 용혼석의 경우, 이 처리를 하지 않으면 속성이 하나도 붙지 않게 된다.)
// 아이템 몰에서 인벤으로 옮기는 부분에서 용혼석 특수 처리
// (몰에서 만드는 아이템은 item_proto에 정의된대로 속성이 붙기 때문에,
// 용혼석의 경우, 이 처리를 하지 않으면 속성이 하나도 붙지 않게 된다.)
if (pkItem->IsDragonSoul())
{
if (bMall)
@ -2163,7 +2163,7 @@ void CInputMain::SafeboxCheckout(LPCHARACTER ch, const char * c_pData, bool bMal
SPDLOG_ERROR("pkItem->GetProto() == NULL (id : {})",pkItem->GetID());
return ;
}
// 100% 확률로 속성이 붙어야 하는데 안 붙어있다면 새로 붙힌다. ...............
// 100% 확률로 속성이 붙어야 하는데 안 붙어있다면 새로 붙힌다. ...............
if (100 == pkItem->GetProto()->bAlterToMagicItemPct && 0 == pkItem->GetAttributeCount())
{
pkItem->AlterToMagicItem();
@ -2232,7 +2232,7 @@ void CInputMain::PartyInviteAnswer(LPCHARACTER ch, const char * c_pData)
LPCHARACTER pInviter = CHARACTER_MANAGER::instance().Find(p->leader_vid);
// pInviter 가 ch 에게 파티 요청을 했었다.
// pInviter 가 ch 에게 파티 요청을 했었다.
if (!pInviter)
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC6\xC4\xC6\xBC> \xC6\xC4\xC6\xBC\xBF\xE4\xC3\xBB\xC0\xBB \xC7\xD1 \xC4\xB3\xB8\xAF\xC5\xCD\xB8\xA6 \xC3\xA3\xC0\xBB\xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
@ -2554,7 +2554,7 @@ int CInputMain::Guild(LPCHARACTER ch, const char * data, size_t uiBytes)
{
case GUILD_SUBHEADER_CG_DEPOSIT_MONEY:
{
// by mhh : 길드자금은 당분간 넣을 수 없다.
// by mhh : 길드자금은 당분간 넣을 수 없다.
return SubPacketLen;
const int gold = std::min(*reinterpret_cast<const int*>(c_pData), __deposit_limit());
@ -2577,7 +2577,7 @@ int CInputMain::Guild(LPCHARACTER ch, const char * data, size_t uiBytes)
case GUILD_SUBHEADER_CG_WITHDRAW_MONEY:
{
// by mhh : 길드자금은 당분간 뺄 수 없다.
// by mhh : 길드자금은 당분간 뺄 수 없다.
return SubPacketLen;
const int gold = std::min(*reinterpret_cast<const int*>(c_pData), 500000);
@ -2773,7 +2773,7 @@ int CInputMain::Guild(LPCHARACTER ch, const char * data, size_t uiBytes)
if (length > GUILD_COMMENT_MAX_LEN)
{
// 잘못된 길이.. 끊어주자.
// 잘못된 길이.. 끊어주자.
SPDLOG_ERROR("POST_COMMENT: {} comment too long (length: {})", ch->GetName(), length);
ch->GetDesc()->SetPhase(PHASE_CLOSE);
return -1;

View File

@ -67,7 +67,7 @@ int CInputP2P::Relay(LPDESC d, const char * c_pData, size_t uiBytes)
{
if (pkChr->IsBlockMode(BLOCK_WHISPER))
{
// 귓속말 거부 상태에서 귓속말 거부.
// 귓속말 거부 상태에서 귓속말 거부.
return p->lSize;
}
@ -75,12 +75,12 @@ int CInputP2P::Relay(LPDESC d, const char * c_pData, size_t uiBytes)
memcpy(buf, c_pbData, std::min<size_t>(p->lSize, sizeof(buf)));
TPacketGCWhisper* p2 = (TPacketGCWhisper*) buf;
// bType 상위 4비트: Empire 번호
// bType 하위 4비트: EWhisperType
// bType 상위 4비트: Empire 번호
// bType 하위 4비트: EWhisperType
BYTE bToEmpire = (p2->bType >> 4);
p2->bType = p2->bType & 0x0F;
if(p2->bType == 0x0F) {
// 시스템 메세지 귓속말은 bType의 상위비트까지 모두 사용함.
// 시스템 메세지 귓속말은 bType의 상위비트까지 모두 사용함.
p2->bType = WHISPER_TYPE_SYSTEM;
} else {
if (!pkChr->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
@ -338,7 +338,7 @@ void CInputP2P::XmasWarpSanta(const char * c_pData)
else
iNextSpawnDelay = 50 * 60;
xmas::SpawnSanta(p->lMapIndex, iNextSpawnDelay); // 50분있다가 새로운 산타가 나타남 (한국은 20분)
xmas::SpawnSanta(p->lMapIndex, iNextSpawnDelay); // 50분있다가 새로운 산타가 나타남 (한국은 20분)
TPacketGGXmasWarpSantaReply pack_reply;
pack_reply.bHeader = HEADER_GG_XMAS_WARP_SANTA_REPLY;

View File

@ -294,7 +294,7 @@ LPITEM CItem::RemoveFromCharacter()
LPCHARACTER pOwner = m_pOwner;
if (m_bEquipped) // 장착되었는가?
if (m_bEquipped) // 장착되었는가?
{
Unequip();
//pOwner->UpdatePacket();
@ -318,7 +318,7 @@ LPITEM CItem::RemoveFromCharacter()
{
TItemPos cell(INVENTORY, m_wCell);
if (false == cell.IsDefaultInventoryPosition() && false == cell.IsBeltInventoryPosition()) // 아니면 소지품에?
if (false == cell.IsDefaultInventoryPosition() && false == cell.IsBeltInventoryPosition()) // 아니면 소지품에?
SPDLOG_ERROR("CItem::RemoveFromCharacter: Invalid Item Position");
else
{
@ -470,16 +470,16 @@ bool CItem::CanUsedBy(LPCHARACTER ch)
int CItem::FindEquipCell(LPCHARACTER ch, int iCandidateCell)
{
// 코스츔 아이템(ITEM_COSTUME)은 WearFlag 없어도 됨. (sub type으로 착용위치 구분. 귀찮게 또 wear flag 줄 필요가 있나..)
// 용혼석(ITEM_DS, ITEM_SPECIAL_DS)도 SUB_TYPE으로 구분. 신규 반지, 벨트는 ITEM_TYPE으로 구분 -_-
// 코스츔 아이템(ITEM_COSTUME)은 WearFlag 없어도 됨. (sub type으로 착용위치 구분. 귀찮게 또 wear flag 줄 필요가 있나..)
// 용혼석(ITEM_DS, ITEM_SPECIAL_DS)도 SUB_TYPE으로 구분. 신규 반지, 벨트는 ITEM_TYPE으로 구분 -_-
if ((0 == GetWearFlag() || ITEM_TOTEM == GetType()) && ITEM_COSTUME != GetType() && ITEM_DS != GetType() && ITEM_SPECIAL_DS != GetType() && ITEM_RING != GetType() && ITEM_BELT != GetType())
return -1;
// 용혼석 슬롯을 WEAR로 처리할 수가 없어서(WEAR는 최대 32개까지 가능한데 용혼석을 추가하면 32가 넘는다.)
// 인벤토리의 특정 위치((INVENTORY_MAX_NUM + WEAR_MAX_NUM)부터 (INVENTORY_MAX_NUM + WEAR_MAX_NUM + DRAGON_SOUL_DECK_MAX_NUM * DS_SLOT_MAX - 1)까지)를
// 용혼석 슬롯으로 정함.
// return 할 때에, INVENTORY_MAX_NUM을 뺀 이유는,
// 본래 WearCell이 INVENTORY_MAX_NUM를 빼고 return 하기 때문.
// 용혼석 슬롯을 WEAR로 처리할 수가 없어서(WEAR는 최대 32개까지 가능한데 용혼석을 추가하면 32가 넘는다.)
// 인벤토리의 특정 위치((INVENTORY_MAX_NUM + WEAR_MAX_NUM)부터 (INVENTORY_MAX_NUM + WEAR_MAX_NUM + DRAGON_SOUL_DECK_MAX_NUM * DS_SLOT_MAX - 1)까지)를
// 용혼석 슬롯으로 정함.
// return 할 때에, INVENTORY_MAX_NUM을 뺀 이유는,
// 본래 WearCell이 INVENTORY_MAX_NUM를 빼고 return 하기 때문.
if (GetType() == ITEM_DS || GetType() == ITEM_SPECIAL_DS)
{
if (iCandidateCell < 0)
@ -540,7 +540,7 @@ int CItem::FindEquipCell(LPCHARACTER ch, int iCandidateCell)
return WEAR_UNIQUE1;
}
// 수집 퀘스트를 위한 아이템이 박히는곳으로 한번 박히면 절대 ?E수 없다.
// 수집 퀘스트를 위한 아이템이 박히는곳으로 한번 박히면 절대 ?E수 없다.
else if (GetWearFlag() & WEARABLE_ABILITY)
{
if (!ch->GetWear(WEAR_ABILITY1))
@ -587,12 +587,12 @@ void CItem::ModifyPoints(bool bAdd)
{
int accessoryGrade;
// 무기와 갑옷만 소켓을 적용시킨다.
// 무기와 갑옷만 소켓을 적용시킨다.
if (false == IsAccessoryForSocket())
{
if (m_pProto->bType == ITEM_WEAPON || m_pProto->bType == ITEM_ARMOR)
{
// 소켓이 속성강화에 사용되는 경우 적용하지 않는다 (ARMOR_WRIST ARMOR_NECK ARMOR_EAR)
// 소켓이 속성강화에 사용되는 경우 적용하지 않는다 (ARMOR_WRIST ARMOR_NECK ARMOR_EAR)
for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
{
DWORD dwVnum;
@ -651,12 +651,12 @@ void CItem::ModifyPoints(bool bAdd)
m_pOwner->ApplyPoint(m_pProto->aApplies[i].bType, bAdd ? value : -value);
}
}
// 초승달의 반지, 할로윈 사탕, 행복의 반지, 영원한 사랑의 펜던트의 경우
// 기존의 하드 코딩으로 강제로 속성을 부여했지만,
// 그 부분을 제거하고 special item group 테이블에서 속성을 부여하도록 변경하였다.
// 하지만 하드 코딩되어있을 때 생성된 아이템이 남아있을 수도 있어서 특수처리 해놓는다.
// 이 아이템들의 경우, 밑에 ITEM_UNIQUE일 때의 처리로 속성이 부여되기 때문에,
// 아이템에 박혀있는 attribute는 적용하지 않고 넘어간다.
// 초승달의 반지, 할로윈 사탕, 행복의 반지, 영원한 사랑의 펜던트의 경우
// 기존의 하드 코딩으로 강제로 속성을 부여했지만,
// 그 부분을 제거하고 special item group 테이블에서 속성을 부여하도록 변경하였다.
// 하지만 하드 코딩되어있을 때 생성된 아이템이 남아있을 수도 있어서 특수처리 해놓는다.
// 이 아이템들의 경우, 밑에 ITEM_UNIQUE일 때의 처리로 속성이 부여되기 때문에,
// 아이템에 박혀있는 attribute는 적용하지 않고 넘어간다.
if (true == CItemVnumHelper::IsRamadanMoonRing(GetVnum()) || true == CItemVnumHelper::IsHalloweenCandy(GetVnum())
|| true == CItemVnumHelper::IsHappinessRing(GetVnum()) || true == CItemVnumHelper::IsLovePendant(GetVnum()))
{
@ -713,7 +713,7 @@ void CItem::ModifyPoints(bool bAdd)
case ITEM_ARMOR:
{
// 코스츔 body를 입고있다면 armor는 벗던 입던 상관 없이 비주얼에 영향을 주면 안 됨.
// 코스츔 body를 입고있다면 armor는 벗던 입던 상관 없이 비주얼에 영향을 주면 안 됨.
if (0 != m_pOwner->GetWear(WEAR_COSTUME_BODY))
break;
@ -733,33 +733,33 @@ void CItem::ModifyPoints(bool bAdd)
}
break;
// 코스츔 아이템 입었을 때 캐릭터 parts 정보 세팅. 기존 스타일대로 추가함..
// 코스츔 아이템 입었을 때 캐릭터 parts 정보 세팅. 기존 스타일대로 추가함..
case ITEM_COSTUME:
{
DWORD toSetValue = this->GetVnum();
EParts toSetPart = PART_MAX_NUM;
// 갑옷 코스츔
// 갑옷 코스츔
if (GetSubType() == COSTUME_BODY)
{
toSetPart = PART_MAIN;
if (false == bAdd)
{
// 코스츔 갑옷을 벗었을 때 원래 갑옷을 입고 있었다면 그 갑옷으로 look 세팅, 입지 않았다면 default look
// 코스츔 갑옷을 벗었을 때 원래 갑옷을 입고 있었다면 그 갑옷으로 look 세팅, 입지 않았다면 default look
const CItem* pArmor = m_pOwner->GetWear(WEAR_BODY);
toSetValue = (NULL != pArmor) ? pArmor->GetVnum() : m_pOwner->GetOriginalPart(PART_MAIN);
}
}
// 헤어 코스츔
// 헤어 코스츔
else if (GetSubType() == COSTUME_HAIR)
{
toSetPart = PART_HAIR;
// 코스츔 헤어는 shape값을 item proto의 value3에 세팅하도록 함. 특별한 이유는 없고 기존 갑옷(ARMOR_BODY)의 shape값이 프로토의 value3에 있어서 헤어도 같이 value3으로 함.
// [NOTE] 갑옷은 아이템 vnum을 보내고 헤어는 shape(value3)값을 보내는 이유는.. 기존 시스템이 그렇게 되어있음...
// 코스츔 헤어는 shape값을 item proto의 value3에 세팅하도록 함. 특별한 이유는 없고 기존 갑옷(ARMOR_BODY)의 shape값이 프로토의 value3에 있어서 헤어도 같이 value3으로 함.
// [NOTE] 갑옷은 아이템 vnum을 보내고 헤어는 shape(value3)값을 보내는 이유는.. 기존 시스템이 그렇게 되어있음...
toSetValue = (true == bAdd) ? this->GetValue(3) : 0;
}
@ -820,7 +820,7 @@ bool CItem::EquipTo(LPCHARACTER ch, BYTE bWearCell)
return false;
}
// 용혼석 슬롯 index는 WEAR_MAX_NUM 보다 큼.
// 용혼석 슬롯 index는 WEAR_MAX_NUM 보다 큼.
if (IsDragonSoul())
{
if (bWearCell < WEAR_MAX_NUM || bWearCell >= WEAR_MAX_NUM + DRAGON_SOUL_DECK_MAX_NUM * DS_SLOT_MAX)
@ -847,7 +847,7 @@ bool CItem::EquipTo(LPCHARACTER ch, BYTE bWearCell)
if (GetOwner())
RemoveFromCharacter();
ch->SetWear(bWearCell, this); // 여기서 패킷 나감
ch->SetWear(bWearCell, this); // 여기서 패킷 나감
m_pOwner = ch;
m_bEquipped = true;
@ -905,7 +905,7 @@ bool CItem::Unequip()
return false;
}
//신규 말 아이템 제거시 처리
//신규 말 아이템 제거시 처리
if (IsRideItem())
ClearMountAttributeAndAffect();
@ -1209,7 +1209,7 @@ void CItem::AlterToMagicItem()
}
}
// 100% 확률로 좋은 속성 하나
// 100% 확률로 좋은 속성 하나
PutAttribute(aiItemMagicAttributePercentHigh);
if (Random::get(1, 100) <= iSecondPct)
@ -1295,8 +1295,8 @@ EVENTFUNC(unique_expire_event)
}
else
{
// 게임 내에 시간제 아이템들이 빠릿빠릿하게 사라지지 않는 버그가 있어
// 수정
// 게임 내에 시간제 아이템들이 빠릿빠릿하게 사라지지 않는 버그가 있어
// 수정
// by rtsummit
if (pkItem->GetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME) - cur < 600)
return PASSES_PER_SEC(pkItem->GetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME) - cur);
@ -1306,9 +1306,9 @@ EVENTFUNC(unique_expire_event)
}
}
// 시간 후불제
// timer를 시작할 때에 시간 차감하는 것이 아니라,
// timer가 발화할 때에 timer가 동작한 시간 만큼 시간 차감을 한다.
// 시간 후불제
// timer를 시작할 때에 시간 차감하는 것이 아니라,
// timer가 발화할 때에 timer가 동작한 시간 만큼 시간 차감을 한다.
EVENTFUNC(timer_based_on_wear_expire_event)
{
item_event_info* info = dynamic_cast<item_event_info*>( event->info );
@ -1327,7 +1327,7 @@ EVENTFUNC(timer_based_on_wear_expire_event)
pkItem->SetTimerBasedOnWearExpireEvent(NULL);
pkItem->SetSocket(ITEM_SOCKET_REMAIN_SEC, 0);
// 일단 timer based on wear 용혼석은 시간 다 되었다고 없애지 않는다.
// 일단 timer based on wear 용혼석은 시간 다 되었다고 없애지 않는다.
if (pkItem->IsDragonSoul())
{
DSManager::instance().DeactivateDragonSoul(pkItem);
@ -1419,7 +1419,7 @@ void CItem::StartUniqueExpireEvent()
if (m_pkUniqueExpireEvent)
return;
//기간제 아이템일 경우 시간제 아이템은 동작하지 않는다
//기간제 아이템일 경우 시간제 아이템은 동작하지 않는다
if (IsRealTimeItem())
return;
@ -1442,14 +1442,14 @@ void CItem::StartUniqueExpireEvent()
SetUniqueExpireEvent(event_create(unique_expire_event, info, PASSES_PER_SEC(iSec)));
}
// 시간 후불제
// timer_based_on_wear_expire_event 설명 참조
// 시간 후불제
// timer_based_on_wear_expire_event 설명 참조
void CItem::StartTimerBasedOnWearExpireEvent()
{
if (m_pkTimerBasedOnWearExpireEvent)
return;
//기간제 아이템일 경우 시간제 아이템은 동작하지 않는다
//기간제 아이템일 경우 시간제 아이템은 동작하지 않는다
if (IsRealTimeItem())
return;
@ -1458,7 +1458,7 @@ void CItem::StartTimerBasedOnWearExpireEvent()
int iSec = GetSocket(0);
// 남은 시간을 분단위로 끊기 위해...
// 남은 시간을 분단위로 끊기 위해...
if (0 != iSec)
{
iSec %= 60;
@ -1477,7 +1477,7 @@ void CItem::StopUniqueExpireEvent()
if (!m_pkUniqueExpireEvent)
return;
if (GetValue(2) != 0) // 게임시간제 이외의 아이템은 UniqueExpireEvent를 중단할 수 없다.
if (GetValue(2) != 0) // 게임시간제 이외의 아이템은 UniqueExpireEvent를 중단할 수 없다.
return;
// HARD CODING
@ -1514,12 +1514,12 @@ int CItem::GetSpecialGroup() const
}
//
// 악세서리 소켓 처리.
// 악세서리 소켓 처리.
//
bool CItem::IsAccessoryForSocket()
{
return (m_pProto->bType == ITEM_ARMOR && (m_pProto->bSubType == ARMOR_WRIST || m_pProto->bSubType == ARMOR_NECK || m_pProto->bSubType == ARMOR_EAR)) ||
(m_pProto->bType == ITEM_BELT); // 2013년 2월 새로 추가된 '벨트' 아이템의 경우 기획팀에서 악세서리 소켓 시스템을 그대로 이용하자고 함.
(m_pProto->bType == ITEM_BELT); // 2013년 2월 새로 추가된 '벨트' 아이템의 경우 기획팀에서 악세서리 소켓 시스템을 그대로 이용하자고 함.
}
void CItem::SetAccessorySocketGrade(int iGrade)
@ -1664,7 +1664,7 @@ void CItem::ClearMountAttributeAndAffect()
}
// fixme
// 이거 지금은 안쓴데... 근데 혹시나 싶어서 남겨둠.
// 이거 지금은 안쓴데... 근데 혹시나 싶어서 남겨둠.
// by rtsummit
bool CItem::IsNewMountItem()
{
@ -1711,7 +1711,7 @@ void CItem::AccessorySocketDegrade()
}
}
// ring에 item을 박을 수 있는지 여부를 체크해서 리턴
// ring에 item을 박을 수 있는지 여부를 체크해서 리턴
static const bool CanPutIntoRing(LPITEM ring, LPITEM item)
{
const DWORD vnum = item->GetVnum();
@ -1932,10 +1932,10 @@ int CItem::GetLevelLimit()
bool CItem::OnAfterCreatedItem()
{
// 아이템을 한 번이라도 사용했다면, 그 이후엔 사용 중이지 않아도 시간이 차감되는 방식
// 아이템을 한 번이라도 사용했다면, 그 이후엔 사용 중이지 않아도 시간이 차감되는 방식
if (-1 != this->GetProto()->cLimitRealTimeFirstUseIndex)
{
// Socket1에 아이템의 사용 횟수가 기록되어 있으니, 한 번이라도 사용한 아이템은 타이머를 시작한다.
// Socket1에 아이템의 사용 횟수가 기록되어 있으니, 한 번이라도 사용한 아이템은 타이머를 시작한다.
if (0 != GetSocket(1))
{
StartRealTimeExpireEvent();
@ -1948,8 +1948,8 @@ bool CItem::OnAfterCreatedItem()
#ifdef __AUCTION__
// 경매장
// window를 경매장으로 한다.
// 경매장
// window를 경매장으로 한다.
bool CItem::MoveToAuction()
{
@ -2016,7 +2016,7 @@ int CItem::GiveMoreTime_Per(float fPercent)
return given_time;
}
}
// 우선 용혼석에 관해서만 하도록 한다.
// 우선 용혼석에 관해서만 하도록 한다.
else
return 0;
}
@ -2040,7 +2040,7 @@ int CItem::GiveMoreTime_Fix(DWORD dwTime)
return dwTime;
}
}
// 우선 용혼석에 관해서만 하도록 한다.
// 우선 용혼석에 관해서만 하도록 한다.
else
return 0;
}
@ -2065,7 +2065,7 @@ int CItem::GetDuration()
bool CItem::IsSameSpecialGroup(const LPITEM item) const
{
// 서로 VNUM이 같다면 같은 그룹인 것으로 간주
// 서로 VNUM이 같다면 같은 그룹인 것으로 간주
if (this->GetVnum() == item->GetVnum())
return true;

View File

@ -20,7 +20,7 @@ void CItemAddonManager::ApplyAddonTo(int iAddonType, LPITEM pItem)
return;
}
// TODO 일단 하드코딩으로 평타 스킬 수치 변경만 경우만 적용받게한다.
// TODO 일단 하드코딩으로 평타 스킬 수치 변경만 경우만 적용받게한다.
int iSkillBonus = std::clamp((int) (Random::get<std::normal_distribution<>>(0, 5) + 0.5f), -30, 30);
int iNormalHitBonus = 0;

View File

@ -24,7 +24,7 @@ int CItem::GetAttributeSetIndex()
switch (GetSubType())
{
case ARMOR_BODY:
// case COSTUME_BODY: // 코스츔 갑옷은 일반 갑옷과 동일한 Attribute Set을 이용하여 랜덤속성 붙음 (ARMOR_BODY == COSTUME_BODY)
// case COSTUME_BODY: // 코스츔 갑옷은 일반 갑옷과 동일한 Attribute Set을 이용하여 랜덤속성 붙음 (ARMOR_BODY == COSTUME_BODY)
return ATTRIBUTE_SET_BODY;
case ARMOR_WRIST:
@ -37,7 +37,7 @@ int CItem::GetAttributeSetIndex()
return ATTRIBUTE_SET_NECK;
case ARMOR_HEAD:
// case COSTUME_HAIR: // 코스츔 헤어는 일반 투구 아이템과 동일한 Attribute Set을 이용하여 랜덤속성 붙음 (ARMOR_HEAD == COSTUME_HAIR)
// case COSTUME_HAIR: // 코스츔 헤어는 일반 투구 아이템과 동일한 Attribute Set을 이용하여 랜덤속성 붙음 (ARMOR_HEAD == COSTUME_HAIR)
return ATTRIBUTE_SET_HEAD;
case ARMOR_SHIELD:
@ -125,7 +125,7 @@ void CItem::PutAttributeWithLevel(BYTE bLevel)
int total = 0;
// 붙일 수 있는 속성 배열을 구축
// 붙일 수 있는 속성 배열을 구축
for (int i = 0; i < MAX_APPLY_NUM; ++i)
{
const TItemAttrTable & r = g_map_itemAttr[i];
@ -137,7 +137,7 @@ void CItem::PutAttributeWithLevel(BYTE bLevel)
}
}
// 구축된 배열로 확률 계산을 통해 붙일 속성 선정
// 구축된 배열로 확률 계산을 통해 붙일 속성 선정
unsigned int prob = Random::get(1, total);
int attr_idx = APPLY_NONE;
@ -162,7 +162,7 @@ void CItem::PutAttributeWithLevel(BYTE bLevel)
const TItemAttrTable & r = g_map_itemAttr[attr_idx];
// 종류별 속성 레벨 최대값 제한
// 종류별 속성 레벨 최대값 제한
if (bLevel > r.bMaxLevelBySet[iAttributeSet])
bLevel = r.bMaxLevelBySet[iAttributeSet];

View File

@ -80,7 +80,7 @@ bool ITEM_MANAGER::Initialize(TItemTable * table, int size)
if (m_vec_prototype[i].dwRefinedVnum)
m_map_ItemRefineFrom.insert(std::make_pair(m_vec_prototype[i].dwRefinedVnum, m_vec_prototype[i].dwVnum));
// NOTE : QUEST_GIVE 플래그는 npc 이벤트로 발생.
// NOTE : QUEST_GIVE 플래그는 npc 이벤트로 발생.
if (m_vec_prototype[i].bType == ITEM_QUEST || IS_SET(m_vec_prototype[i].dwFlags, ITEM_FLAG_QUEST_USE | ITEM_FLAG_QUEST_USE_MULTIPLE))
quest::CQuestManager::instance().RegisterNPCVnum(m_vec_prototype[i].dwVnum);
@ -155,7 +155,7 @@ LPITEM ITEM_MANAGER::CreateItem(DWORD vnum, DWORD count, DWORD id, bool bTryMagi
{
if (vnum == 50300 && bTryMagic)
{
// 수련서를 아이템 번호를 다르게 만들어 준다.
// 수련서를 아이템 번호를 다르게 만들어 준다.
DWORD dwSkillVnum;
do
@ -181,7 +181,7 @@ LPITEM ITEM_MANAGER::CreateItem(DWORD vnum, DWORD count, DWORD id, bool bTryMagi
LPITEM item = NULL;
//id로 검사해서 존재한다면 -- 리턴!
//id로 검사해서 존재한다면 -- 리턴!
if (m_map_pkItemByID.find(id) != m_map_pkItemByID.end())
{
item = m_map_pkItemByID[id];
@ -190,7 +190,7 @@ LPITEM ITEM_MANAGER::CreateItem(DWORD vnum, DWORD count, DWORD id, bool bTryMagi
return NULL;
}
//아이템 하나 할당하고
//아이템 하나 할당하고
#ifdef M2_USE_POOL
item = pool_.Construct();
#else
@ -199,15 +199,15 @@ LPITEM ITEM_MANAGER::CreateItem(DWORD vnum, DWORD count, DWORD id, bool bTryMagi
bool bIsNewItem = (0 == id);
//초기화 하고. 테이블 셋하고
//초기화 하고. 테이블 셋하고
item->Initialize();
item->SetProto(table);
item->SetMaskVnum(dwMaskVnum);
if (item->GetType() == ITEM_ELK) // 돈은 ID가 필요없고 저장도 필요없다.
if (item->GetType() == ITEM_ELK) // 돈은 ID가 필요없고 저장도 필요없다.
item->SetSkipSave(true);
// Unique ID를 세팅하자
// Unique ID를 세팅하자
else if (!bIsNewItem)
{
item->SetID(id);
@ -217,16 +217,16 @@ LPITEM ITEM_MANAGER::CreateItem(DWORD vnum, DWORD count, DWORD id, bool bTryMagi
{
item->SetID(GetNewID());
if (item->GetType() == ITEM_UNIQUE) // 유니크 아이템은 생성시에 소켓에 남은시간을 기록한다.
if (item->GetType() == ITEM_UNIQUE) // 유니크 아이템은 생성시에 소켓에 남은시간을 기록한다.
{
if (item->GetValue(2) == 0)
item->SetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME, item->GetValue(0)); // 게임 시간 유니크
item->SetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME, item->GetValue(0)); // 게임 시간 유니크
else
{
//int globalTime = get_global_time();
//int lastTime = item->GetValue(0);
//int endTime = get_global_time() + item->GetValue(0);
item->SetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME, get_global_time() + item->GetValue(0)); // 실시간 유니크
item->SetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME, get_global_time() + item->GetValue(0)); // 실시간 유니크
}
}
}
@ -255,9 +255,9 @@ LPITEM ITEM_MANAGER::CreateItem(DWORD vnum, DWORD count, DWORD id, bool bTryMagi
break;
}
if (item->GetType() == ITEM_ELK) // 돈은 아무 처리가 필요하지 않음
if (item->GetType() == ITEM_ELK) // 돈은 아무 처리가 필요하지 않음
;
else if (item->IsStackable()) // 합칠 수 있는 아이템의 경우
else if (item->IsStackable()) // 합칠 수 있는 아이템의 경우
{
count = std::clamp<int>(count, 1, ITEM_MAX_COUNT);
@ -285,7 +285,7 @@ LPITEM ITEM_MANAGER::CreateItem(DWORD vnum, DWORD count, DWORD id, bool bTryMagi
for (int i=0 ; i < ITEM_LIMIT_MAX_NUM ; i++)
{
// 아이템 생성 시점부터 사용하지 않아도 시간이 차감되는 방식
// 아이템 생성 시점부터 사용하지 않아도 시간이 차감되는 방식
if (LIMIT_REAL_TIME == item->GetLimitType(i))
{
if (item->GetLimitValue(i))
@ -300,11 +300,11 @@ LPITEM ITEM_MANAGER::CreateItem(DWORD vnum, DWORD count, DWORD id, bool bTryMagi
item->StartRealTimeExpireEvent();
}
// 기존 유니크 아이템처럼 착용시에만 사용가능 시간이 차감되는 방식
// 기존 유니크 아이템처럼 착용시에만 사용가능 시간이 차감되는 방식
else if (LIMIT_TIMER_BASED_ON_WEAR == item->GetLimitType(i))
{
// 이미 착용중인 아이템이면 타이머를 시작하고, 새로 만드는 아이템은 사용 가능 시간을 세팅해준다. (
// 아이템몰로 지급하는 경우에는 이 로직에 들어오기 전에 Socket0 값이 세팅이 되어 있어야 한다.
// 이미 착용중인 아이템이면 타이머를 시작하고, 새로 만드는 아이템은 사용 가능 시간을 세팅해준다. (
// 아이템몰로 지급하는 경우에는 이 로직에 들어오기 전에 Socket0 값이 세팅이 되어 있어야 한다.
if (true == item->IsEquipped())
{
item->StartTimerBasedOnWearExpireEvent();
@ -316,16 +316,16 @@ LPITEM ITEM_MANAGER::CreateItem(DWORD vnum, DWORD count, DWORD id, bool bTryMagi
duration = item->GetLimitValue(i);
if (0 == duration)
duration = 60 * 60 * 10; // 정보가 아무것도 없으면 디폴트로 10시간 세팅
duration = 60 * 60 * 10; // 정보가 아무것도 없으면 디폴트로 10시간 세팅
item->SetSocket(0, duration);
}
}
}
if (id == 0) // 새로 만드는 아이템일 때만 처리
if (id == 0) // 새로 만드는 아이템일 때만 처리
{
// 새로추가되는 약초들일경우 성능을 다르게처리
// 새로추가되는 약초들일경우 성능을 다르게처리
if (ITEM_BLEND==item->GetType())
{
if (Blend_Item_find(item->GetVnum()))
@ -352,7 +352,7 @@ LPITEM ITEM_MANAGER::CreateItem(DWORD vnum, DWORD count, DWORD id, bool bTryMagi
if (table->bGainSocketPct)
item->AlterToSocketItem(table->bGainSocketPct);
// 50300 == 기술 수련서
// 50300 == 기술 수련서
if (vnum == 50300 || vnum == ITEM_SKILLFORGET_VNUM)
{
DWORD dwSkillVnum;
@ -404,7 +404,7 @@ LPITEM ITEM_MANAGER::CreateItem(DWORD vnum, DWORD count, DWORD id, bool bTryMagi
}
}
// 새로 생성되는 용혼석 처리.
// 새로 생성되는 용혼석 처리.
if (item->IsDragonSoul() && 0 == id)
{
DSManager::instance().DragonSoulItemInitialize(item);
@ -473,7 +473,7 @@ void ITEM_MANAGER::Update()
this_it = it++;
LPITEM item = *this_it;
// SLOW_QUERY 플래그가 있는 것은 종료시에만 저장한다.
// SLOW_QUERY 플래그가 있는 것은 종료시에만 저장한다.
if (item->GetOwner() && IS_SET(item->GetFlag(), ITEM_FLAG_SLOW_QUERY))
continue;
@ -496,7 +496,7 @@ void ITEM_MANAGER::RemoveItem(LPITEM item, const char * c_pszReason)
// SAFEBOX_TIME_LIMIT_ITEM_BUG_FIX
if (item->GetWindow() == MALL || item->GetWindow() == SAFEBOX)
{
// 20050613.ipkn.시간제 아이템이 상점에 있을 경우 시간만료시 서버가 다운된다.
// 20050613.ipkn.시간제 아이템이 상점에 있을 경우 시간만료시 서버가 다운된다.
CSafebox* pSafebox = item->GetWindow() == MALL ? o->GetMall() : o->GetSafebox();
if (pSafebox)
{
@ -760,8 +760,8 @@ class CItemDropInfo
extern std::vector<CItemDropInfo> g_vec_pkCommonDropItem[MOB_RANK_MAX_NUM];
// 20050503.ipkn.
// iMinimum 보다 작으면 iDefault 세팅 (단, iMinimum은 0보다 커야함)
// 1, 0 식으로 ON/OFF 되는 방식을 지원하기 위해 존재
// iMinimum 보다 작으면 iDefault 세팅 (단, iMinimum은 0보다 커야함)
// 1, 0 식으로 ON/OFF 되는 방식을 지원하기 위해 존재
int GetDropPerKillPct(int iMinimum, int iDefault, int iDeltaPercent, const char * c_pszFlag)
{
int iVal = 0;
@ -781,8 +781,8 @@ int GetDropPerKillPct(int iMinimum, int iDefault, int iDeltaPercent, const char
if (iVal == 0)
return 0;
// 기본 세팅일때 (iDeltaPercent=100)
// 40000 iVal 마리당 하나 느낌을 주기 위한 상수임
// 기본 세팅일때 (iDeltaPercent=100)
// 40000 iVal 마리당 하나 느낌을 주기 위한 상수임
return (40000 * iDeltaPercent / iVal);
}
@ -930,7 +930,7 @@ bool ITEM_MANAGER::CreateDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller, std::
CMobItemGroup* pGroup = it->second;
// MOB_DROP_ITEM_BUG_FIX
// 20050805.myevan.MobDropItem 에 아이템이 없을 경우 CMobItemGroup::GetOne() 접근시 문제 발생 수정
// 20050805.myevan.MobDropItem 에 아이템이 없을 경우 CMobItemGroup::GetOne() 접근시 문제 발생 수정
if (pGroup && !pGroup->IsEmpty())
{
int iPercent = 40000 * iDeltaPercent / pGroup->GetKillPerDrop();
@ -997,7 +997,7 @@ bool ITEM_MANAGER::CreateDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller, std::
}
}
// 잡템
// 잡템
if (pkChr->GetMobDropItemVnum())
{
itertype(m_map_dwEtcItemDropProb) it = m_map_dwEtcItemDropProb.find(pkChr->GetMobDropItemVnum());
@ -1046,14 +1046,14 @@ bool ITEM_MANAGER::CreateDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller, std::
pdw[1] = 1;
pdw[2] = quest::CQuestManager::instance().GetEventFlag("lotto_round");
// 행운의 서는 소켓을 설정한다
// 행운의 서는 소켓을 설정한다
DBManager::instance().ReturnQuery(QID_LOTTO, pkKiller->GetPlayerID(), pdw,
"INSERT INTO lotto_list VALUES(0, 'server%s', %u, NOW())",
get_table_postfix(), pkKiller->GetPlayerID());
}
//
// 스페셜 드롭 아이템
// 스페셜 드롭 아이템
//
CreateQuestDropItem(pkChr, pkKiller, vec_item, iDeltaPercent, iRandRange);
@ -1064,7 +1064,7 @@ bool ITEM_MANAGER::CreateDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller, std::
}
//
// 승룡곡 천의동굴 2층에서만 수룡방 입장권
// 승룡곡 천의동굴 2층에서만 수룡방 입장권
//
if (LC_IsYMIR() || LC_IsKorea())
{
@ -1081,21 +1081,21 @@ bool ITEM_MANAGER::CreateDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller, std::
}
//
// 승룡곡 1층, 2층에서만 7,8 스킬입문서 드롭
// 승룡곡 1층, 2층에서만 7,8 스킬입문서 드롭
//
if (LC_IsYMIR() || LC_IsKorea())
{
switch (pkKiller->GetMapIndex())
{
case 72: // 천의동굴 1층
case 73: // 천의동굴 2층
case 72: // 천의동굴 1층
case 73: // 천의동굴 2층
{
int vnum = 0;
if (2403 == pkChr->GetRaceNum()) // 천의법사
vnum = 69200; // 7스킬 입문서
else if (2411 == pkChr->GetRaceNum()) // 진천의병사
vnum = 69201; // 8스킬 입문서
if (2403 == pkChr->GetRaceNum()) // 천의법사
vnum = 69200; // 7스킬 입문서
else if (2411 == pkChr->GetRaceNum()) // 진천의병사
vnum = 69201; // 8스킬 입문서
else
break;
@ -1250,11 +1250,11 @@ bool DropEvent_CharStone_SetValue(const std::string& name, int value)
// END_OF_DROPEVENT_CHARSTONE
// fixme
// 위의 것과 함께 quest로 뺄것 빼보자.
// 이거 너무 더럽잖아...
// ??.. 하드코딩 싫다 ㅜㅠ
// 계량 아이템 보상 시작.
// by rtsummit 고치자 진짜
// 위의 것과 함께 quest로 뺄것 빼보자.
// 이거 너무 더럽잖아...
// ??.. 하드코딩 싫다 ㅜㅠ
// 계량 아이템 보상 시작.
// by rtsummit 고치자 진짜
static struct DropEvent_RefineBox
{
int percent_low;
@ -1371,7 +1371,7 @@ bool DropEvent_RefineBox_SetValue(const std::string& name, int value)
return true;
}
// 개량 아이템 보상 끝.
// 개량 아이템 보상 끝.
void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller, std::vector<LPITEM> & vec_item, int iDeltaPercent, int iRandRange)
@ -1391,7 +1391,7 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
// END_OF_DROPEVENT_CHARSTONE
__DropEvent_RefineBox_DropItem(*pkKiller, *pkChr, *this, vec_item);
// 크리스마스 양말
// 크리스마스 양말
if (quest::CQuestManager::instance().GetEventFlag("xmas_sock"))
{
//const DWORD SOCK_ITEM_VNUM = 50010;
@ -1433,7 +1433,7 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
}
}
// 월광 보합
// 월광 보합
if (quest::CQuestManager::instance().GetEventFlag("drop_moon"))
{
const DWORD ITEM_VNUM = 50011;
@ -1479,7 +1479,7 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
}
}
//육각보합
//육각보합
if (GetDropPerKillPct(100, g_iUseLocale ? 2000 : 800, iDeltaPercent, "2006_drop") >= Random::get(1, iRandRange))
{
SPDLOG_DEBUG("\xC0\xB0\xB0\xA2\xBA\xB8\xC7\xD5 DROP EVENT ");
@ -1491,7 +1491,7 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
}
//육각보합+
//육각보합+
if (GetDropPerKillPct(100, g_iUseLocale ? 2000 : 800, iDeltaPercent, "2007_drop") >= Random::get(1, iRandRange))
{
SPDLOG_DEBUG("\xC0\xB0\xB0\xA2\xBA\xB8\xC7\xD5 DROP EVENT ");
@ -1502,17 +1502,17 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
vec_item.push_back(item);
}
// 새해 폭죽 이벤트
// 새해 폭죽 이벤트
if (GetDropPerKillPct(/* minimum */ 100, /* default */ 1000, iDeltaPercent, "newyear_fire") >= Random::get(1, iRandRange))
{
// 중국은 폭죽, 한국 팽이
// 중국은 폭죽, 한국 팽이
const DWORD ITEM_VNUM_FIRE = g_iUseLocale ? 50107 : 50108;
if ((item = CreateItem(ITEM_VNUM_FIRE, 1, 0, true)))
vec_item.push_back(item);
}
// 새해 대보름 원소 이벤트
// 새해 대보름 원소 이벤트
if (GetDropPerKillPct(100, 500, iDeltaPercent, "newyear_moon") >= Random::get(1, iRandRange))
{
SPDLOG_DEBUG("EVENT NEWYEAR_MOON DROP");
@ -1524,7 +1524,7 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
vec_item.push_back(item);
}
// 발렌타인 데이 이벤트. OGE의 요구에 따라 event 최소값을 1로 변경.(다른 이벤트는 일단 그대로 둠.)
// 발렌타인 데이 이벤트. OGE의 요구에 따라 event 최소값을 1로 변경.(다른 이벤트는 일단 그대로 둠.)
if (GetDropPerKillPct(1, g_iUseLocale ? 2000 : 800, iDeltaPercent, "valentine_drop") >= Random::get(1, iRandRange))
{
SPDLOG_DEBUG("EVENT VALENTINE_DROP");
@ -1536,7 +1536,7 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
vec_item.push_back(item);
}
// 아이스크림 이벤트
// 아이스크림 이벤트
if (GetDropPerKillPct(100, g_iUseLocale ? 2000 : 800, iDeltaPercent, "icecream_drop") >= Random::get(1, iRandRange))
{
const static DWORD icecream = 50123;
@ -1545,8 +1545,8 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
vec_item.push_back(item);
}
// new 크리스마스 이벤트
// 53002 : 아기 순록 소환권
// new 크리스마스 이벤트
// 53002 : 아기 순록 소환권
if ((pkKiller->CountSpecifyItem(53002) > 0) && (GetDropPerKillPct(50, 100, iDeltaPercent, "new_xmas_event") >= Random::get(1, iRandRange)))
{
const static DWORD xmas_sock = 50010;
@ -1590,7 +1590,7 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
vec_item.push_back(item);
}
// 월드컵 이벤트
// 월드컵 이벤트
if ( GetDropPerKillPct(100, g_iUseLocale ? 2000 : 800, iDeltaPercent, "football_drop") >= Random::get(1, iRandRange) )
{
const static DWORD football_item = 50096;
@ -1599,7 +1599,7 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
vec_item.push_back(item);
}
// 화이트 데이 이벤트
// 화이트 데이 이벤트
if (GetDropPerKillPct(100, g_iUseLocale ? 2000 : 800, iDeltaPercent, "whiteday_drop") >= Random::get(1, iRandRange))
{
SPDLOG_DEBUG("EVENT WHITEDAY_DROP");
@ -1610,7 +1610,7 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
vec_item.push_back(item);
}
// 어린이날 수수께끼 상자 이벤트
// 어린이날 수수께끼 상자 이벤트
if (pkKiller->GetLevel()>=50)
{
if (GetDropPerKillPct(100, 1000, iDeltaPercent, "kids_day_drop_high") >= Random::get(1, iRandRange))
@ -1632,7 +1632,7 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
}
}
// 올림픽 드롭 이벤트
// 올림픽 드롭 이벤트
if (pkChr->GetLevel() >= 30 && GetDropPerKillPct(50, 100, iDeltaPercent, "medal_part_drop") >= Random::get(1, iRandRange))
{
const static DWORD drop_items[] = { 30265, 30266, 30267, 30268, 30269 };
@ -1643,7 +1643,7 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
}
// ADD_GRANDMASTER_SKILL
// 혼석 아이템 드롭
// 혼석 아이템 드롭
if (pkChr->GetLevel() >= 40 && pkChr->GetMobRank() >= MOB_RANK_BOSS && GetDropPerKillPct(/* minimum */ 1, /* default */ 1000, iDeltaPercent, "three_skill_item") / GetThreeSkillLevelAdjust(pkChr->GetLevel()) >= Random::get(1, iRandRange))
{
const DWORD ITEM_VNUM = 50513;
@ -1654,7 +1654,7 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
// END_OF_ADD_GRANDMASTER_SKILL
//
// 종자 아이템 drop
// 종자 아이템 drop
//
if (GetDropPerKillPct(100, 1000, iDeltaPercent, "dragon_boat_festival_drop") >= Random::get(1, iRandRange))
{
@ -1664,7 +1664,7 @@ void ITEM_MANAGER::CreateQuestDropItem(LPCHARACTER pkChr, LPCHARACTER pkKiller,
vec_item.push_back(item);
}
// 무신의 축복서용 만년한철 drop
// 무신의 축복서용 만년한철 drop
if (pkKiller->GetLevel() >= 15 && quest::CQuestManager::instance().GetEventFlag("mars_drop"))
{
const DWORD ITEM_HANIRON = 70035;
@ -1726,8 +1726,8 @@ DWORD ITEM_MANAGER::GetMaskVnum(DWORD dwVnum)
return 0;
}
// pkNewItem으로 모든 속성과 소켓 값들을 목사하는 함수.
// 기존에 char_item.cpp 파일에 있던 로컬함수인 TransformRefineItem 그대로 복사함
// pkNewItem으로 모든 속성과 소켓 값들을 목사하는 함수.
// 기존에 char_item.cpp 파일에 있던 로컬함수인 TransformRefineItem 그대로 복사함
void ITEM_MANAGER::CopyAllAttrTo(LPITEM pkOldItem, LPITEM pkNewItem)
{
// ACCESSORY_REFINE
@ -1742,7 +1742,7 @@ void ITEM_MANAGER::CopyAllAttrTo(LPITEM pkOldItem, LPITEM pkNewItem)
// END_OF_ACCESSORY_REFINE
else
{
// 여기서 깨진석이 자동적으로 청소 됨
// 여기서 깨진석이 자동적으로 청소 됨
for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
{
if (!pkOldItem->GetSocket(i))
@ -1751,19 +1751,19 @@ void ITEM_MANAGER::CopyAllAttrTo(LPITEM pkOldItem, LPITEM pkNewItem)
pkNewItem->SetSocket(i, 1);
}
// 소켓 설정
// 소켓 설정
int slot = 0;
for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
{
int socket = pkOldItem->GetSocket(i);
const int ITEM_BROKEN_METIN_VNUM = 28960; // 이건 뭐 똑같은 상수가 3군데나 있냐... 하나로 해놓지ㅠㅠㅠ 나는 패스 홍이 할꺼임
const int ITEM_BROKEN_METIN_VNUM = 28960; // 이건 뭐 똑같은 상수가 3군데나 있냐... 하나로 해놓지ㅠㅠㅠ 나는 패스 홍이 할꺼임
if (socket > 2 && socket != ITEM_BROKEN_METIN_VNUM)
pkNewItem->SetSocket(slot++, socket);
}
}
// 매직 아이템 설정
// 매직 아이템 설정
pkOldItem->CopyAttributeTo(pkNewItem);
}

View File

@ -78,7 +78,7 @@ bool ITEM_MANAGER::ReadCommonDropItemFile(const char * c_pszFileName)
if (!ITEM_MANAGER::instance().GetVnumByOriginalName(d[i].szItemName, dwItemVnum))
{
// <EFBFBD≯<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ã<EFBFBD><C3A3><EFBFBD><EFBFBD> <20><>ȣ<EFBFBD><C8A3> <20>˻<EFBFBD>
// 이름으로 못찾으면 번호로 검색
str_to_number(dwItemVnum, d[i].szItemName);
if (!ITEM_MANAGER::instance().GetTable(dwItemVnum))
{
@ -405,7 +405,7 @@ bool ITEM_MANAGER::ConvSpecialDropItemFile()
str_to_number(iRarePct, pTok->at(3).c_str());
}
// 1 "<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ü<EFBFBD>" 1 100
// 1 "기술 수련서" 1 100
if (0 == dwVnum)
fprintf(fp, " %d %s %d %d\n", k, name.c_str(), iCount, iProb);
else

View File

@ -48,7 +48,7 @@ const char *quote_find_end(const char *string)
{
if (quote && *tmp == '\\' && *(tmp + 1))
{
// \ 다음 문자가 " 면 스킵한다.
// \ 다음 문자가 " 면 스킵한다.
switch (*(tmp + 1))
{
case '"':

View File

@ -79,7 +79,7 @@ int check_name_independent(const char * str)
if (CBanwordManager::instance().CheckString(str, strlen(str)))
return 0;
// 몬스터 이름으로는 만들 수 없다.
// 몬스터 이름으로는 만들 수 없다.
char szTmp[256];
str_lower(str, szTmp, sizeof(szTmp));
@ -120,12 +120,12 @@ int check_name_gb2312(const char * str)
b1 = str[i++];
b2 = str[i++];
// 중국 간체는 첫번째 바이트 범위가 b0 -> f7 까지고
// 두번째 바이트 범위가 a1 -> fe 다.
// 중국 간체는 첫번째 바이트 범위가 b0 -> f7 까지고
// 두번째 바이트 범위가 a1 -> fe 다.
if (b1 < 0xb0 || b1 > 0xf7 || b2 < 0xa1 || b2 > 0xfe)
return 0;
// 예외가 있다.
// 예외가 있다.
for (j = 0; j < 5; j++)
if (b1 == exceptions[j][0] && b2 == exceptions[j][1])
return 0;
@ -172,8 +172,8 @@ int check_name_big5(const char * str )
b[0] = b2;
b[1] = b1;
// 중국 번체 ( big5 : 홍콩 )
// 범위는 다음과 같다.
// 중국 번체 ( big5 : 홍콩 )
// 범위는 다음과 같다.
// big5: 0xA140--0xF9D5
// extended big5: 0x40--0x7E and 0xA1--0xFE
@ -230,15 +230,15 @@ int check_name_latin1(const char * str)
for (tmp = str; *tmp; ++tmp)
{
// 한글이 아니고 빈칸이면 잘못된 것
// 한글이 아니고 빈칸이면 잘못된 것
if (isspace(*tmp))
return 0;
// 한글이 아니고 숫자라면 적합하다.
// 한글이 아니고 숫자라면 적합하다.
if (isdigit(*tmp))
continue;
// 한글이 아니고 영문이라면 적합하다.
// 한글이 아니고 영문이라면 적합하다.
if (isalpha(*tmp))
continue;
@ -275,7 +275,7 @@ int check_name_alphabet(const char * str)
for (tmp = str; *tmp; ++tmp)
{
// 알파벳과 수자만 허용
// 알파벳과 수자만 허용
if (isdigit(*tmp) || isalpha(*tmp))
continue;
else
@ -324,7 +324,7 @@ int check_name_sjis(const char *str)
const char *p = str;
const char *e = str + strlen(str); // NULL position
// 일본은 캐릭터 이름길이 16byte 까지
// 일본은 캐릭터 이름길이 16byte 까지
if ( strlen(str) < 2 || strlen(str) > 16 )
return 0;
@ -337,7 +337,7 @@ int check_name_sjis(const char *str)
return false;
// END_OF_DISABLE_SPECIAL_CHAR_NAMING
// 이문자는 허용되지 않는다.
// 이문자는 허용되지 않는다.
if ((BYTE)p[0]==0x81 && (BYTE)p[1]==0x40) return false;
p += 2;
@ -345,7 +345,7 @@ int check_name_sjis(const char *str)
}
else
{
// 영문이나 수자는 허용한다.
// 영문이나 수자는 허용한다.
if (isalpha(*p) || isdigit(*p))
{
p += 1;
@ -888,7 +888,7 @@ static void __LocaleService_Init_Singapore()
check_name = check_name_alphabet;
g_iUseLocale = true;
//exp_table = exp_table_newcibn; 2013 09 11 CYH europe 과 동일하게 간다.
//exp_table = exp_table_newcibn; 2013 09 11 CYH europe 과 동일하게 간다.
}
static void __LocaleService_Init_Vietnam()
@ -1309,18 +1309,18 @@ bool LC_IsEurope()
case LC_DENMARK:
case LC_BULGARIA:
case LC_CROATIA:
case LC_MEXICO: // 남미지만 GF에서 서비스 하므로 여기 넣음
case LC_ARABIA: // 중동이지만 GF에서 서비스 하므로 여기 넣음
case LC_MEXICO: // 남미지만 GF에서 서비스 하므로 여기 넣음
case LC_ARABIA: // 중동이지만 GF에서 서비스 하므로 여기 넣음
case LC_CZECH:
case LC_ROMANIA:
case LC_HUNGARY:
case LC_NETHERLANDS:
case LC_USA:
case LC_WE_KOREA: // 한국이지만 UK 버전 기반이므로 여기 넣음
case LC_TAIWAN: // 대만이지만 WE_KOREA 버전 기반이므로 여기 넣음
case LC_JAPAN: // 일본이지만 WE(World Edition -_-) 버전이므로 여기 넣음
case LC_WE_KOREA: // 한국이지만 UK 버전 기반이므로 여기 넣음
case LC_TAIWAN: // 대만이지만 WE_KOREA 버전 기반이므로 여기 넣음
case LC_JAPAN: // 일본이지만 WE(World Edition -_-) 버전이므로 여기 넣음
case LC_NEWCIBN:
case LC_CANADA: // 캐나다 GF에서 서비스 시작
case LC_CANADA: // 캐나다 GF에서 서비스 시작
return true;
}

View File

@ -86,10 +86,10 @@ void WriteMallocMessage(const char* p1, const char* p2, const char* p3, const ch
#endif
// TRAFFIC_PROFILER
static const DWORD TRAFFIC_PROFILE_FLUSH_CYCLE = 3600; ///< TrafficProfiler 의 Flush cycle. 1시간 간격
static const DWORD TRAFFIC_PROFILE_FLUSH_CYCLE = 3600; ///< TrafficProfiler 의 Flush cycle. 1시간 간격
// END_OF_TRAFFIC_PROFILER
// 게임과 연결되는 소켓
// 게임과 연결되는 소켓
volatile int num_events_called = 0;
int max_bytes_written = 0;
int current_bytes_written = 0;
@ -227,7 +227,7 @@ void heartbeat(LPHEART ht, int pulse)
t = get_dword_time();
// 1초마다
// 1초마다
if (!(pulse % ht->passes_per_sec))
{
if (!g_bAuthServer)
@ -279,14 +279,14 @@ void heartbeat(LPHEART ht, int pulse)
}
//
// 25 PPS(Pulse per second) 라고 가정할 때
// 25 PPS(Pulse per second) 라고 가정할 때
//
// 약 1.16초마다
// 약 1.16초마다
if (!(pulse % (passes_per_sec + 4)))
CHARACTER_MANAGER::instance().ProcessDelayedSave();
// 약 5.08초마다
// 약 5.08초마다
if (!(pulse % (passes_per_sec * 5 + 2)))
{
ITEM_MANAGER::instance().Update();
@ -849,7 +849,7 @@ int io_loop(event_base * base)
LPDESC d;
int num_events, event_idx;
DESC_MANAGER::instance().DestroyClosed(); // PHASE_CLOSE인 접속들을 끊어준다.
DESC_MANAGER::instance().DestroyClosed(); // PHASE_CLOSE인 접속들을 끊어준다.
DESC_MANAGER::instance().TryConnect();
// Process network events

View File

@ -21,19 +21,19 @@ namespace marriage
DWORD dwVnum;
int value[MAX_LOVE_GRADE];
} g_ItemBonus[MAX_MARRIAGE_UNIQUE_ITEM] = {
{ 71069, { 4, 5, 6, 8, } }, // 관통 증가
{ 71070, { 10, 12, 15, 20, } }, // 경험치 증가
{ 71071, { 4, 5, 6, 8, } }, // 크리티컬 증가
{ 71072, { -4, -5, -6, -8, } }, // 상대방 공격력 감소
{ 71073, { 20, 25, 30, 40, } }, // 공격력 증가 (절대값)
{ 71074, { 12, 16, 20, 30, } }, // 방어력 증가 (절대값)
{ 71069, { 4, 5, 6, 8, } }, // 관통 증가
{ 71070, { 10, 12, 15, 20, } }, // 경험치 증가
{ 71071, { 4, 5, 6, 8, } }, // 크리티컬 증가
{ 71072, { -4, -5, -6, -8, } }, // 상대방 공격력 감소
{ 71073, { 20, 25, 30, 40, } }, // 공격력 증가 (절대값)
{ 71074, { 12, 16, 20, 30, } }, // 방어력 증가 (절대값)
//{ 71069, 1, 2, 3, 6, 8, }, // 관통 증가
//{ 71070, 5, 7, 10, 15, 20, }, // 경험치 증가
//{ 71071, 1, 2, 3, 6, 8, }, // 크리티컬 증가
//{ 71072, 5, 10, 15, 20, 30, }, // 상대방이 입은 데미지를 나에게로
//{ 71073, 10, 15, 20, 25, 40, }, // 공격력 증가 (절대값)
//{ 71074, 5, 10, 15, 20, 30, }, // 방어력 증가 (절대값)
//{ 71069, 1, 2, 3, 6, 8, }, // 관통 증가
//{ 71070, 5, 7, 10, 15, 20, }, // 경험치 증가
//{ 71071, 1, 2, 3, 6, 8, }, // 크리티컬 증가
//{ 71072, 5, 10, 15, 20, 30, }, // 상대방이 입은 데미지를 나에게로
//{ 71073, 10, 15, 20, 25, 40, }, // 공격력 증가 (절대값)
//{ 71074, 5, 10, 15, 20, 30, }, // 방어력 증가 (절대값)
};
const int MARRIAGE_POINT_PER_DAY = 1;
@ -101,17 +101,17 @@ namespace marriage
else
days /= 86400;
// 기본 50%
// 기본 50%
// 원앙의 깃털 사용중일 때 :
// 날짜에 의한 영향 80% 하루당 8%
// 전투에 의한 영향 80%
// 토탈 100%
// 원앙의 깃털 사용중일 때 :
// 날짜에 의한 영향 80% 하루당 8%
// 전투에 의한 영향 80%
// 토탈 100%
// 비사용중일 때 :
// 날짜에 의한 영향 60% 하루당 6%
// 전투에 의한 영향 60%
// 토탈 100%
// 비사용중일 때 :
// 날짜에 의한 영향 60% 하루당 6%
// 전투에 의한 영향 60%
// 토탈 100%
return std::min(50 + std::min(days * point_per_day, max_limit) + std::min(love_point / 1000000, max_limit), 100);
}
@ -124,11 +124,11 @@ namespace marriage
return ch1->GetMapIndex() == ch2->GetMapIndex();
// 파티 체크가 사라졌음
// 파티 체크가 사라졌음
/*if (!ch1->GetParty() || ch1->GetParty() != ch2->GetParty())
return false;*/
// 거리 체크가 사라졌음
// 거리 체크가 사라졌음
/*const int DISTANCE = 5000;
if (labs(ch1->GetX() - ch2->GetX()) > DISTANCE)
@ -140,15 +140,15 @@ namespace marriage
return (DISTANCE_APPROX(ch1->GetX() - ch2->GetX(), ch1->GetY() - ch2->GetY()) < DISTANCE);*/
}
// 금슬 수치
// 금슬 수치
int TMarriage::GetBonus(DWORD dwItemVnum, bool bShare, LPCHARACTER me)
{
if (!is_married)
return 0;
// 주변에 없을때는 자기 기능만 적용된다.
// 주변에 없을때는 자기 기능만 적용된다.
// 해당 아이템이 어떤 기능을 하는지 찾는다.
// 해당 아이템이 어떤 기능을 하는지 찾는다.
int iFindedBonusIndex=0;
{
for (iFindedBonusIndex = 0; iFindedBonusIndex < MAX_MARRIAGE_UNIQUE_ITEM; ++iFindedBonusIndex)
@ -163,7 +163,7 @@ namespace marriage
if (bShare)
{
// 두명의 보너스를 합한다.
// 두명의 보너스를 합한다.
int count = 0;
if (NULL != ch1 && ch1->IsEquipUniqueItem(dwItemVnum))
count ++;
@ -178,7 +178,7 @@ namespace marriage
}
else
{
// 상대방 것만 계산
// 상대방 것만 계산
int count = 0;
if (me != ch1 && NULL!= ch1 && ch1->IsEquipUniqueItem(dwItemVnum))
count ++;
@ -208,7 +208,7 @@ namespace marriage
SendLoverInfo(ch2, name1, GetMarriagePoint());
}
// 둘 다 이 프로세스에 로그인 중이면 포인터를 연결하고 이벤트 발생
// 둘 다 이 프로세스에 로그인 중이면 포인터를 연결하고 이벤트 발생
if (IsOnline())
{
ch1->SetMarryPartner(ch2);
@ -217,7 +217,7 @@ namespace marriage
StartNearCheckEvent();
}
// 둘 다 로그인 되어 있다면 패킷을 보낸다.
// 둘 다 로그인 되어 있다면 패킷을 보낸다.
if (is_married)
{
LPDESC d1, d2;
@ -581,7 +581,7 @@ namespace marriage
if (A && B)
{
// 웨딩 맵 요청을 보낸다
// 웨딩 맵 요청을 보낸다
TPacketWeddingRequest p;
p.dwPID1 = dwPID1;
p.dwPID2 = dwPID2;
@ -703,11 +703,11 @@ namespace marriage
if (!pwi)
return;
// 결혼자들을 워프시켜야함
// 결혼자들을 워프시켜야함
pMarriage->WarpToWeddingMap(dwPID1);
pMarriage->WarpToWeddingMap(dwPID2);
// 등록해서 메뉴창에서 이름나와야함
// 등록해서 메뉴창에서 이름나와야함
m_setWedding.insert(make_pair(dwPID1, dwPID2));
}
@ -726,7 +726,7 @@ namespace marriage
return;
}
// 맵에서 빼내야합니다
// 맵에서 빼내야합니다
if (map_allow_find(WEDDING_MAP_INDEX))
if (!WeddingManager::instance().End(pMarriage->pWeddingInfo->dwMapIndex))
{

View File

@ -1,4 +1,4 @@
//#define __MATRIX_MAIN_ENABLE__ // define 되어 있으면 main 함수가 포함된다. Unit test 시에 사용
//#define __MATRIX_MAIN_ENABLE__ // define 되어 있으면 main 함수가 포함된다. Unit test 시에 사용
#ifndef __MATRIX_MAIN_ENABLE__
#include "stdafx.h"
#else

View File

@ -240,11 +240,11 @@ void MessengerManager::RemoveAllList(keyA account)
{
std::set<keyT> company(m_Relation[account]);
/* SQL Data 삭제 */
/* SQL Data 삭제 */
DBManager::instance().Query("DELETE FROM messenger_list%s WHERE account='%s' OR companion='%s'",
get_table_postfix(), account.c_str(), account.c_str());
/* 내가 가지고있는 리스트 삭제 */
/* 내가 가지고있는 리스트 삭제 */
for (std::set<keyT>::iterator iter = company.begin();
iter != company.end();
iter++ )
@ -252,7 +252,7 @@ void MessengerManager::RemoveAllList(keyA account)
this->RemoveFromList(account, *iter);
}
/* 복사한 데이타 삭제 */
/* 복사한 데이타 삭제 */
for (std::set<keyT>::iterator iter = company.begin();
iter != company.end();
)

View File

@ -86,10 +86,10 @@ int CMonarch::HealMyEmpire(LPCHARACTER ch ,DWORD price)
f.m_bEmpire = Empire;
SECTREE_MANAGER::instance().for_each(iMapIndex, f);
// DB에 돈 삭감 보내기
// DB에 돈 삭감 보내기
SendtoDBDecMoney(price, Empire, ch);
// 쿨타임 설정
// 쿨타임 설정
ch->SetMC(CHARACTER::MI_HEAL);
if (test_server)
@ -139,7 +139,7 @@ bool CMonarch::SendtoDBDecMoney(int Money, BYTE bEmpire, LPCHARACTER ch)
if (GetMoney(bEmpire) - Money < 0)
return false;
// 실제 줄이는 부분은 서버에 갔다 온 다음에 처리된다
// 실제 줄이는 부분은 서버에 갔다 온 다음에 처리된다
int nEmpire = bEmpire;
db_clientdesc->DBPacketHeader(HEADER_GD_DEC_MONARCH_MONEY, ch->GetDesc()->GetHandle(), sizeof(int) + sizeof(int));
@ -153,7 +153,7 @@ bool CMonarch::AddMoney(int Money, BYTE bEmpire)
if (bEmpire >= _countof(m_MonarchInfo.money))
return false;
// 20억 이상 입금 불가능
// 20억 이상 입금 불가능
if (GetMoney(bEmpire) + Money > 2000000000)
return false;
@ -236,7 +236,7 @@ void CMonarch::PowerUp(BYTE Empire, bool On)
m_PowerUp[Empire] = On;
// 군주 사자후 쿨타임
// 군주 사자후 쿨타임
m_PowerUpCT[Empire] = thecore_pulse() + PASSES_PER_SEC(60 * 10);
}
@ -247,13 +247,13 @@ void CMonarch::DefenseUp(BYTE Empire, bool On)
m_DefenseUp[Empire] = On;
// 군주 금강권 쿨타임
// 군주 금강권 쿨타임
m_DefenseUpCT[Empire] = thecore_pulse() + PASSES_PER_SEC(60 * 10);
}
bool IsMonarchWarpZone (int map_idx)
{
// 아귀동굴, 천의동굴.
// 아귀동굴, 천의동굴.
if (map_idx >= 10000)
map_idx /= 10000;
@ -263,9 +263,9 @@ bool IsMonarchWarpZone (int map_idx)
case 302:
case 303:
case 304:
//던전
case 351: // 적룡성
case 352: // 백룡지성
//던전
case 351: // 적룡성
case 352: // 백룡지성
return false;
}

View File

@ -476,7 +476,7 @@ bool CMotion::LoadMobSkillFromFile(const char * c_pszFileName, CMob* pMob, int i
continue;
case MOTION_EVENT_TYPE_SPECIAL_ATTACKING:
// 구 데이터는 하나 라고 가정
// 구 데이터는 하나 라고 가정
if (!rkTextFileLoader.SetChildNode("spheredata", 0))
{
SPDLOG_ERROR("Motion: no sphere data {}", c_pszFileName);

View File

@ -173,7 +173,7 @@ void P2P_MANAGER::Login(LPDESC d, const TPacketGGLogin * p)
CGuildManager::instance().P2PLoginMember(pkCCI->dwPID);
CPartyManager::instance().P2PLogin(pkCCI->dwPID, pkCCI->szName);
// CCI가 생성시에만 메신저를 업데이트하면 된다.
// CCI가 생성시에만 메신저를 업데이트하면 된다.
if (UpdateP2P) {
std::string name(pkCCI->szName);
MessengerManager::instance().P2PLogin(name);

View File

@ -84,7 +84,7 @@ void SendPanamaList(LPDESC d)
DWORD* ivs = (DWORD*)pack.abIV;
for (int i = 0; i != 32 / sizeof(DWORD); i++)
{
ivs[i] ^= d->GetPanamaKey() + i * 16777619; // 더블워드단위로 변형된 파나마 키를 XOR 해준다
ivs[i] ^= d->GetPanamaKey() + i * 16777619; // 더블워드단위로 변형된 파나마 키를 XOR 해준다
}
++it;

View File

@ -34,7 +34,7 @@ void CPartyManager::DeleteAllParty()
}
}
bool CPartyManager::SetParty(LPCHARACTER ch) // PC만 사용해야 한다!!
bool CPartyManager::SetParty(LPCHARACTER ch) // PC만 사용해야 한다!!
{
TPartyMap::iterator it = m_map_pkParty.find(ch->GetPlayerID());
@ -295,7 +295,7 @@ void CParty::Destroy()
{
SPDLOG_TRACE("Party::Destroy");
// PC가 만든 파티면 파티매니저에 맵에서 PID를 삭제해야 한다.
// PC가 만든 파티면 파티매니저에 맵에서 PID를 삭제해야 한다.
if (m_bPCParty)
{
for (TMemberMap::iterator it = m_memberMap.begin(); it != m_memberMap.end(); ++it)
@ -327,7 +327,7 @@ void CParty::Destroy()
}
else
{
// NPC일 경우 일정 시간 후 전투 중이 아닐 때 사라지게 하는 이벤트를 시작시킨다.
// NPC일 경우 일정 시간 후 전투 중이 아닐 때 사라지게 하는 이벤트를 시작시킨다.
rMember.pCharacter->SetLastAttacked(dwTime);
rMember.pCharacter->StartDestroyWhenIdleEvent();
}
@ -458,7 +458,7 @@ void CParty::Join(DWORD dwPID)
TPacketPartyAdd p;
p.dwLeaderPID = GetLeaderPID();
p.dwPID = dwPID;
p.bState = PARTY_ROLE_NORMAL; // #0000790: [M2EU] CZ 크래쉬 증가: 초기화 중요!
p.bState = PARTY_ROLE_NORMAL; // #0000790: [M2EU] CZ 크래쉬 증가: 초기화 중요!
db_clientdesc->DBPacket(HEADER_GD_PARTY_ADD, 0, &p, sizeof(p));
}
}
@ -504,11 +504,11 @@ void CParty::P2PQuit(DWORD dwPID)
if (m_bPCParty)
CPartyManager::instance().SetPartyMember(dwPID, NULL);
// 리더가 나가면 파티는 해산되어야 한다.
// 리더가 나가면 파티는 해산되어야 한다.
if (bRole == PARTY_ROLE_LEADER)
CPartyManager::instance().DeleteParty(this);
// 이 아래는 코드를 추가하지 말 것!!! 위 DeleteParty 하면 this는 없다.
// 이 아래는 코드를 추가하지 말 것!!! 위 DeleteParty 하면 this는 없다.
}
void CParty::Quit(DWORD dwPID)
@ -546,7 +546,7 @@ void CParty::Link(LPCHARACTER pkChr)
return;
}
// 플레이어 파티일 경우 업데이트 이벤트 생성
// 플레이어 파티일 경우 업데이트 이벤트 생성
if (m_bPCParty && !m_eventUpdate)
{
party_update_event_info* info = AllocEventInfo<party_update_event_info>();
@ -643,7 +643,7 @@ void CParty::Unlink(LPCHARACTER pkChr)
if (pkChr->IsPC())
{
SendPartyUnlinkOneToAll(pkChr);
//SendPartyUnlinkAllToOne(pkChr); // 끊기는 것이므로 구지 Unlink 패킷을 보낼 필요 없다.
//SendPartyUnlinkAllToOne(pkChr); // 끊기는 것이므로 구지 Unlink 패킷을 보낼 필요 없다.
if (it->second.bRole == PARTY_ROLE_LEADER)
{
@ -651,7 +651,7 @@ void CParty::Unlink(LPCHARACTER pkChr)
if (it->second.pCharacter->GetDungeon())
{
// TODO: 던젼에 있으면 나머지도 나간다
// TODO: 던젼에 있으면 나머지도 나간다
FExitDungeon f;
ForEachNearMember(f);
}
@ -898,9 +898,9 @@ void CParty::SendMessage(LPCHARACTER ch, BYTE bMsg, DWORD dwArg1, DWORD dwArg2)
}
break;
case PM_ATTACKED_BY: // 공격 받았음, 리더에게 도움을 요청
case PM_ATTACKED_BY: // 공격 받았음, 리더에게 도움을 요청
{
// 리더가 없을 때
// 리더가 없을 때
LPCHARACTER pkChrVictim = ch->GetVictim();
if (!pkChrVictim)
@ -1067,7 +1067,7 @@ void CParty::RemoveBonusForOne(DWORD pid)
void CParty::HealParty()
{
// XXX DELETEME 클라이언트 완료될때까지
// XXX DELETEME 클라이언트 완료될때까지
{
return;
}
@ -1355,7 +1355,7 @@ void CParty::Update()
bool bLongTimeExpBonusChanged = false;
// 파티 결성 후 충분한 시간이 지나면 경험치 보너스를 받는다.
// 파티 결성 후 충분한 시간이 지나면 경험치 보너스를 받는다.
if (!m_iLongTimeExpBonus && (get_dword_time() - m_dwPartyStartTime > PARTY_ENOUGH_MINUTE_FOR_EXP_BONUS * 60 * 1000 / (g_iUseLocale?1:2)))
{
bLongTimeExpBonusChanged = true;
@ -1400,9 +1400,9 @@ void CParty::Update()
if (!m_bCanUsePartyHeal && m_iLeadership >= 18)
m_dwPartyHealTime = get_dword_time();
m_bCanUsePartyHeal = m_iLeadership >= 18; // 통솔력 18 이상은 힐을 사용할 수 있음.
m_bCanUsePartyHeal = m_iLeadership >= 18; // 통솔력 18 이상은 힐을 사용할 수 있음.
// 통솔력 40이상은 파티 힐 쿨타임이 적다.
// 통솔력 40이상은 파티 힐 쿨타임이 적다.
DWORD PartyHealCoolTime = (m_iLeadership >= 40) ? PARTY_HEAL_COOLTIME_SHORT * 60 * 1000 : PARTY_HEAL_COOLTIME_LONG * 60 * 1000;
if (m_bCanUsePartyHeal)
@ -1412,7 +1412,7 @@ void CParty::Update()
m_bPartyHealReady = true;
// send heal ready
if (0) // XXX DELETEME 클라이언트 완료될때까지
if (0) // XXX DELETEME 클라이언트 완료될때까지
if (GetLeaderCharacter())
GetLeaderCharacter()->ChatPacket(CHAT_TYPE_COMMAND, "PartyHealReady");
}
@ -1681,7 +1681,7 @@ int CParty::ComputePartyBonusExpPercent()
if (leader && (leader->IsEquipUniqueItem(UNIQUE_ITEM_PARTY_BONUS_EXP) || leader->IsEquipUniqueItem(UNIQUE_ITEM_PARTY_BONUS_EXP_MALL)
|| leader->IsEquipUniqueItem(UNIQUE_ITEM_PARTY_BONUS_EXP_GIFT) || leader->IsEquipUniqueGroup(10010)))
{
// 중국측 육도 적용을 확인해야한다.
// 중국측 육도 적용을 확인해야한다.
if (g_iUseLocale)
{
iBonusPartyExpFromItem = 30;

View File

@ -64,7 +64,7 @@ bool CPolymorphUtils::PolymorphCharacter(LPCHARACTER pChar, LPITEM pItem, const
// dwDuration *= 60;
// 변신 확률 = 캐릭터 레벨 - 몹 레벨 + 둔갑서 레벨 + 29 + 둔갑 스킬 레벨
// 변신 확률 = 캐릭터 레벨 - 몹 레벨 + 둔갑서 레벨 + 29 + 둔갑 스킬 레벨
iPolyPercent = pChar->GetLevel() - pMob->m_table.bLevel + pItem->GetSocket(2) + (29 + bySkillLevel);
if (iPolyPercent <= 0)
@ -83,7 +83,7 @@ bool CPolymorphUtils::PolymorphCharacter(LPCHARACTER pChar, LPITEM pItem, const
pChar->AddAffect(AFFECT_POLYMORPH, POINT_POLYMORPH, pMob->m_table.dwVnum, AFF_POLYMORPH, dwDuration, 0, true);
// 변신 보너스 = 둔갑 스킬 레벨 + 둔갑서 레벨
// 변신 보너스 = 둔갑 스킬 레벨 + 둔갑서 레벨
dwBonusPercent = bySkillLevel + pItem->GetSocket(2);
switch (GetBonusType(pMob->m_table.dwVnum))
@ -123,8 +123,8 @@ bool CPolymorphUtils::UpdateBookPracticeGrade(LPCHARACTER pChar, LPITEM pItem)
bool CPolymorphUtils::GiveBook(LPCHARACTER pChar, DWORD dwMobVnum, DWORD dwPracticeCount, BYTE BookLevel, BYTE LevelLimit)
{
// 소켓0 소켓1 소켓2
// 둔갑할 몬스터 번호 수련정도 둔갑서 레벨
// 소켓0 소켓1 소켓2
// 둔갑할 몬스터 번호 수련정도 둔갑서 레벨
if (pChar == NULL)
return false;
@ -140,9 +140,9 @@ bool CPolymorphUtils::GiveBook(LPCHARACTER pChar, DWORD dwMobVnum, DWORD dwPract
return false;
}
pItem->SetSocket(0, dwMobVnum); // 둔갑할 몬스터 번호
pItem->SetSocket(1, dwPracticeCount); // 수련해야할 횟수
pItem->SetSocket(2, BookLevel); // 수련레벨
pItem->SetSocket(0, dwMobVnum); // 둔갑할 몬스터 번호
pItem->SetSocket(1, dwPracticeCount); // 수련해야할 횟수
pItem->SetSocket(2, BookLevel); // 수련레벨
return true;
}

View File

@ -225,7 +225,7 @@ void CPrivManager::RemoveCharacterPriv(DWORD pid, BYTE type)
int CPrivManager::GetPriv(LPCHARACTER ch, BYTE type)
{
// 캐릭터의 변경 수치가 -라면 무조건 -만 적용되게
// 캐릭터의 변경 수치가 -라면 무조건 -만 적용되게
int val_ch = GetPrivByCharacter(ch->GetPlayerID(), type);
if (val_ch < 0 && !ch->IsEquipUniqueItem(UNIQUE_ITEM_NO_BAD_LUCK_EFFECT))
@ -234,7 +234,7 @@ int CPrivManager::GetPriv(LPCHARACTER ch, BYTE type)
{
int val;
// 개인, 제국, 길드, 전체 중 큰 값을 취한다.
// 개인, 제국, 길드, 전체 중 큰 값을 취한다.
val = std::max(val_ch, GetPrivByEmpire(0, type));
val = std::max(val, GetPrivByEmpire(ch->GetEmpire(), type));

View File

@ -131,7 +131,7 @@ void CPVP::Win(DWORD dwPID)
m_bRevenge = true;
m_players[iSlot].bAgree = true; // 자동으로 동의
m_players[iSlot].bAgree = true; // 자동으로 동의
m_players[!iSlot].bCanRevenge = true;
m_players[!iSlot].bAgree = false;
@ -180,7 +180,7 @@ void CPVPManager::Insert(LPCHARACTER pkChr, LPCHARACTER pkVictim)
if ((pkPVP = Find(kPVP.m_dwCRC)))
{
// 복수할 수 있으면 바로 싸움!
// 복수할 수 있으면 바로 싸움!
if (pkPVP->Agree(pkChr->GetPlayerID()))
{
pkVictim->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s\xB4\xD4\xB0\xFA\xC0\xC7 \xB4\xEB\xB0\xE1 \xBD\xC3\xC0\xDB!"), pkChr->GetName());
@ -299,8 +299,8 @@ void CPVPManager::GiveUp(LPCHARACTER pkChr, DWORD dwKillerPID) // This method is
}
}
// 리턴값: 0 = PK, 1 = PVP
// PVP를 리턴하면 경험치나 아이템을 떨구고 PK면 떨구지 않는다.
// 리턴값: 0 = PK, 1 = PVP
// PVP를 리턴하면 경험치나 아이템을 떨구고 PK면 떨구지 않는다.
bool CPVPManager::Dead(LPCHARACTER pkChr, DWORD dwKillerPID)
{
CPVPSetMap::iterator it = m_map_pkPVPSetByID.find(pkChr->GetPlayerID());
@ -354,7 +354,7 @@ bool CPVPManager::CanAttack(LPCHARACTER pkChr, LPCHARACTER pkVictim)
return false;
}
if (pkChr == pkVictim) // 내가 날 칠라고 하네 -_-
if (pkChr == pkVictim) // 내가 날 칠라고 하네 -_-
return false;
if (pkVictim->IsNPC() && pkChr->IsNPC() && !pkChr->IsGuardNPC())
@ -380,7 +380,7 @@ bool CPVPManager::CanAttack(LPCHARACTER pkChr, LPCHARACTER pkVictim)
case 20116:
case 20117:
case 20118:
//신규 탈것 고급
//신규 탈것 고급
case 20205:
case 20206:
case 20207:
@ -389,21 +389,21 @@ bool CPVPManager::CanAttack(LPCHARACTER pkChr, LPCHARACTER pkVictim)
case 20210:
case 20211:
case 20212:
case 20119: // 라마단 흑마
case 20219: // 라마단 흑마 클론 (할로윈용)
case 20220: // 크리스마스 탈것
case 20221: // 전갑 백웅
case 20222: // 전갑 팬더
case 20119: // 라마단 흑마
case 20219: // 라마단 흑마 클론 (할로윈용)
case 20220: // 크리스마스 탈것
case 20221: // 전갑 백웅
case 20222: // 전갑 팬더
case 20120:
case 20121:
case 20122:
case 20123:
case 20124:
case 20125:
case 20214: // 난폭한 전갑순순록
case 20215: // 용맹한 전갑순순록
case 20217: // 난폭한 전갑암순록
case 20218: // 용맹한 전갑암순록
case 20214: // 난폭한 전갑순순록
case 20215: // 용맹한 전갑순순록
case 20217: // 난폭한 전갑암순록
case 20218: // 용맹한 전갑암순록
break;
default:
@ -460,7 +460,7 @@ bool CPVPManager::CanAttack(LPCHARACTER pkChr, LPCHARACTER pkVictim)
{
if (g_protectNormalPlayer)
{
// 범법자는 평화모드인 착한사람을 공격할 수 없다.
// 범법자는 평화모드인 착한사람을 공격할 수 없다.
if (PK_MODE_PEACE == pkVictim->GetPKMode())
return false;
}
@ -592,7 +592,7 @@ void CPVPManager::SendList(LPDESC d)
if (!pkPVP->m_players[0].dwVID || !pkPVP->m_players[1].dwVID)
continue;
// VID가 둘다 있을 경우에만 보낸다.
// VID가 둘다 있을 경우에만 보낸다.
if (pkPVP->IsFight())
{
pack.bMode = PVP_MODE_FIGHT;
@ -647,7 +647,7 @@ void CPVPManager::Process()
{
CPVP * pvp = (it++)->second;
if (get_dword_time() - pvp->GetLastFightTime() > 600000) // 10분 이상 싸움이 없었으면
if (get_dword_time() - pvp->GetLastFightTime() > 600000) // 10분 이상 싸움이 없었으면
{
pvp->Packet(true);
Delete(pvp);

View File

@ -35,7 +35,7 @@ namespace quest
if (!q.ServerTimer(info->npc_id, info->arg))
return passes_per_sec / 2 + 1;
if (0 == info->time_cycle) // 루프가 아니라면 종료 시킨다.
if (0 == info->time_cycle) // 루프가 아니라면 종료 시킨다.
{
q.ClearServerTimerNotCancel(info->name, info->arg);
M2_DELETE_ARRAY(info->name);
@ -62,7 +62,7 @@ namespace quest
if (!CQuestManager::instance().Timer(info->player_id, info->npc_id))
return (passes_per_sec / 2 + 1);
if (0 == info->time_cycle) // 루프가 아니라면 종료 시킨다.
if (0 == info->time_cycle) // 루프가 아니라면 종료 시킨다.
goto END_OF_TIMER_EVENT;
}
else

View File

@ -443,7 +443,7 @@ namespace quest
}
/**
* @version 05/06/08 Bang2ni - __get_guildid_byname
* @version 05/06/08 Bang2ni - __get_guildid_byname
*/
bool CQuestManager::InitializeLua()
{
@ -688,7 +688,7 @@ namespace quest
if (chReply)
{
// 시간 지나면 알아서 닫힘
// 시간 지나면 알아서 닫힘
}
if (chWait)
@ -708,12 +708,12 @@ namespace quest
SPDLOG_DEBUG("GotoConfirmState vid {} msg '{}', timeout {}", dwVID, szMsg, iTimeout);
// 1. 상대방에게 확인창 띄움
// 2. 나에게 확인 기다린다고 표시하는 창 띄움
// 3. 타임아웃 설정 (타임아웃 되면 상대방 창 닫고 나에게도 창 닫으라고 보냄)
// 1. 상대방에게 확인창 띄움
// 2. 나에게 확인 기다린다고 표시하는 창 띄움
// 3. 타임아웃 설정 (타임아웃 되면 상대방 창 닫고 나에게도 창 닫으라고 보냄)
// 1
// 상대방이 없는 경우는 그냥 상대방에게 보내지 않는다. 타임아웃에 의해서 넘어가게됨
// 상대방이 없는 경우는 그냥 상대방에게 보내지 않는다. 타임아웃에 의해서 넘어가게됨
LPCHARACTER ch = CHARACTER_MANAGER::instance().Find(dwVID);
if (ch && ch->IsPC())
{
@ -749,7 +749,7 @@ namespace quest
AddScript("[INPUT]");
SendScript();
// 시간 제한을 검
// 시간 제한을 검
//event_create(input_timeout_event, dwEI, PASSES_PER_SEC(iTimeout));
}

View File

@ -31,7 +31,7 @@ namespace quest
return 0;
}
if (ch->FindAffect(AFFECT_QUEST_START_IDX, applyOn)) // 퀘스트로 인해 같은 곳에 효과가 걸려있으면 스킵
if (ch->FindAffect(AFFECT_QUEST_START_IDX, applyOn)) // 퀘스트로 인해 같은 곳에 효과가 걸려있으면 스킵
return 0;
int value = (int) lua_tonumber(L, 2);
@ -62,14 +62,14 @@ namespace quest
return 0;
}
int affect_remove_bad(lua_State * L) // 나쁜 효과를 없앰
int affect_remove_bad(lua_State * L) // 나쁜 효과를 없앰
{
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
ch->RemoveBadAffect();
return 0;
}
int affect_remove_good(lua_State * L) // 좋은 효과를 없앰
int affect_remove_good(lua_State * L) // 좋은 효과를 없앰
{
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
ch->RemoveGoodAffect();
@ -104,7 +104,7 @@ namespace quest
return 0;
}
int affect_remove_hair(lua_State * L) // 헤어 효과를 없앤다.
int affect_remove_hair(lua_State * L) // 헤어 효과를 없앤다.
{
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
@ -123,7 +123,7 @@ namespace quest
return 1;
}
// 현재 캐릭터가 AFFECT_TYPE affect를 갖고있으면 bApplyOn 값을 반환하고 없으면 nil을 반환하는 함수.
// 현재 캐릭터가 AFFECT_TYPE affect를 갖고있으면 bApplyOn 값을 반환하고 없으면 nil을 반환하는 함수.
// usage : applyOn = affect.get_apply(AFFECT_TYPE)
int affect_get_apply_on(lua_State * L)
{

View File

@ -991,7 +991,7 @@ namespace quest
return 0;
}
int dungeon_exit(lua_State* L) // 던전에 들어오기 전 위치로 보냄
int dungeon_exit(lua_State* L) // 던전에 들어오기 전 위치로 보냄
{
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
@ -999,7 +999,7 @@ namespace quest
return 0;
}
int dungeon_exit_all(lua_State* L) // 던전에 있는 모든 사람을 던전에 들어오기 전 위치로 보냄
int dungeon_exit_all(lua_State* L) // 던전에 있는 모든 사람을 던전에 들어오기 전 위치로 보냄
{
CQuestManager& q = CQuestManager::instance();
LPDUNGEON pDungeon = q.GetCurrentDungeon();
@ -1127,7 +1127,7 @@ namespace quest
}
};
int dungeon_exit_all_by_item_group (lua_State* L) // 특정 아이템 그룹에 속한 아이템이 없는사람은 강퇴
int dungeon_exit_all_by_item_group (lua_State* L) // 특정 아이템 그룹에 속한 아이템이 없는사람은 강퇴
{
if (!lua_isstring(L, 1))
{
@ -1192,7 +1192,7 @@ namespace quest
}
};
int dungeon_delete_item_in_item_group_from_all(lua_State* L) // 특정 아이템을 던전 내 pc에게서 삭제.
int dungeon_delete_item_in_item_group_from_all(lua_State* L) // 특정 아이템을 던전 내 pc에게서 삭제.
{
if (!lua_isstring(L, 1))
{

View File

@ -790,7 +790,7 @@ namespace quest
return 1;
}
// 새로운 state를 만든다.
// 새로운 state를 만든다.
int _set_quest_state(lua_State* L)
{
if (!lua_isstring(L, 1) || !lua_isstring(L, 2))
@ -1012,7 +1012,7 @@ namespace quest
return 0;
}
//주의: 몹 리젠이 안되는 맵에서만 사용
//주의: 몹 리젠이 안되는 맵에서만 사용
int _regen_in_map( lua_State * L )
{
int iMapIndex = static_cast<int>(lua_tonumber(L, 1));

View File

@ -297,12 +297,12 @@ namespace quest
int guild_change_master(lua_State* L)
{
// 리턴값
// 0 : 입력한 이름이 잘못되었음 ( 문자열이 아님 )
// 1 : 길드장이 아님
// 2 : 지정한 이름의 길드원이 없음
// 3 : 요청 성공
// 4 : 길드가 없음
// 리턴값
// 0 : 입력한 이름이 잘못되었음 ( 문자열이 아님 )
// 1 : 길드장이 아님
// 2 : 지정한 이름의 길드원이 없음
// 3 : 요청 성공
// 4 : 길드가 없음
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
@ -338,23 +338,23 @@ namespace quest
int guild_change_master_with_limit(lua_State* L)
{
// 인자
// arg0 : 새 길드장 이름
// arg1 : 새 길드장 레벨 제한
// arg2 : resign_limit 제한 시간
// arg3 : be_other_leader 제한 시간
// arg4 : be_other_member 제한 시간
// arg5 : 캐시템인가 아닌가
// 인자
// arg0 : 새 길드장 이름
// arg1 : 새 길드장 레벨 제한
// arg2 : resign_limit 제한 시간
// arg3 : be_other_leader 제한 시간
// arg4 : be_other_member 제한 시간
// arg5 : 캐시템인가 아닌가
//
// 리턴값
// 0 : 입력한 이름이 잘못되었음 ( 문자열이 아님 )
// 1 : 길드장이 아님
// 2 : 지정한 이름의 길드원이 없음
// 3 : 요청 성공
// 4 : 길드가 없음
// 5 : 지정한 이름이 온라인이 아님
// 6 : 지정한 캐릭터 레벨이 기준레벨보다 낮음
// 7 : 새 길드장이 be_other_leader 제한에 걸림
// 리턴값
// 0 : 입력한 이름이 잘못되었음 ( 문자열이 아님 )
// 1 : 길드장이 아님
// 2 : 지정한 이름의 길드원이 없음
// 3 : 요청 성공
// 4 : 길드가 없음
// 5 : 지정한 이름이 온라인이 아님
// 6 : 지정한 캐릭터 레벨이 기준레벨보다 낮음
// 7 : 새 길드장이 be_other_leader 제한에 걸림
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();

View File

@ -61,10 +61,10 @@ namespace quest
{
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
// 소환하면 멀리서부터 달려오는지 여부
// 소환하면 멀리서부터 달려오는지 여부
bool bFromFar = lua_isboolean(L, 1) ? lua_toboolean(L, 1) : false;
// 소환수의 vnum
// 소환수의 vnum
DWORD horseVnum= lua_isnumber(L, 2) ? lua_tonumber(L, 2) : 0;
const char* name = lua_isstring(L, 3) ? lua_tostring(L, 3) : 0;
@ -212,10 +212,10 @@ namespace quest
int horse_set_name(lua_State* L)
{
// 리턴값
// 0 : 소유한 말이 없다
// 1 : 잘못된 이름이다
// 2 : 이름 바꾸기 성공
// 리턴값
// 0 : 소유한 말이 없다
// 1 : 잘못된 이름이다
// 2 : 이름 바꾸기 성공
if ( lua_isstring(L, -1) != true ) return 0;

View File

@ -437,7 +437,7 @@ namespace quest
ITEM_MANAGER::instance().FlushDelayedSave(pkNewItem);
pkNewItem->AttrLog();
// 성공!
// 성공!
lua_pushboolean(L, 1);
}

View File

@ -162,7 +162,7 @@ namespace quest
}
if (pMarriage->pWeddingInfo)
{
// 결혼식 끝내기 요청
// 결혼식 끝내기 요청
pMarriage->RequestEndWedding();
}
return 0;

View File

@ -145,7 +145,7 @@ namespace quest
int HealPrice = quest::CQuestManager::instance().GetEventFlag("MonarchHealGold");
if (HealPrice == 0)
HealPrice = 2000000; // 200만
HealPrice = 2000000; // 200만
if (CMonarch::instance().HealMyEmpire(ch, HealPrice))
{
@ -160,7 +160,7 @@ namespace quest
return 1;
}
// 군주의 사자후 퀘스트 함수
// 군주의 사자후 퀘스트 함수
int monarch_powerup(lua_State * L)
{
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
@ -168,7 +168,7 @@ namespace quest
if (!ch)
return 0;
//군주 체크
//군주 체크
if (false==ch->IsMonarch())
{
if (!ch->IsGM())
@ -179,8 +179,8 @@ namespace quest
}
}
//군주 국고 검사
int money_need = 5000000; // 500만
//군주 국고 검사
int money_need = 5000000; // 500만
if (!CMonarch::instance().IsMoneyOk(money_need, ch->GetEmpire()))
{
int NationMoney = CMonarch::instance().GetMoney(ch->GetEmpire());
@ -195,10 +195,10 @@ namespace quest
return 0;
}
//군주의 사자후 적용
//군주의 사자후 적용
CMonarch::instance().PowerUp(ch->GetEmpire(), true);
//군주의 사자후 적용시간
//군주의 사자후 적용시간
int g_nMonarchPowerUpCT = 60 * 3;
monarch_powerup_event_info* info = AllocEventInfo<monarch_powerup_event_info>();
@ -216,7 +216,7 @@ namespace quest
return 1;
}
// 군주의 금강권 퀘스트 함수
// 군주의 금강권 퀘스트 함수
int monarch_defenseup(lua_State * L)
{
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
@ -225,7 +225,7 @@ namespace quest
return 0;
//군주 체크
//군주 체크
if (false==ch->IsMonarch())
{
@ -237,7 +237,7 @@ namespace quest
}
}
int money_need = 5000000; // 500만
int money_need = 5000000; // 500만
if (!CMonarch::instance().IsMoneyOk(money_need, ch->GetEmpire()))
{
int NationMoney = CMonarch::instance().GetMoney(ch->GetEmpire());
@ -252,10 +252,10 @@ namespace quest
return 0;
}
//군주의 금강권 적용
//군주의 금강권 적용
CMonarch::instance().DefenseUp(ch->GetEmpire(), true);
//군주의 금강권 적용 시간
//군주의 금강권 적용 시간
int g_nMonarchDefenseUpCT = 60 * 3;
monarch_defenseup_event_info* info = AllocEventInfo<monarch_defenseup_event_info>();
@ -326,9 +326,9 @@ namespace quest
int x = ch->GetX();
int y = ch->GetY();
#if 0
if (11505 == mob_vnum) // 황금두꺼비
if (11505 == mob_vnum) // 황금두꺼비
{
//군주 국고 검사
//군주 국고 검사
if (!CMonarch::instance().IsMoneyOk(CASTLE_FROG_PRICE, ch->GetEmpire()))
{
int NationMoney = CMonarch::instance().GetMoney(ch->GetEmpire());
@ -340,7 +340,7 @@ namespace quest
if (mob)
{
// 국고감소
// 국고감소
CMonarch::instance().SendtoDBDecMoney(CASTLE_FROG_PRICE, ch->GetEmpire(), ch);
castle_save();
}
@ -417,7 +417,7 @@ namespace quest
{
int money_need = castle_cost_of_hiring_guard(group_vnum);
//군주 국고 검사
//군주 국고 검사
if (!CMonarch::instance().IsMoneyOk(money_need, ch->GetEmpire()))
{
int NationMoney = CMonarch::instance().GetMoney(ch->GetEmpire());
@ -428,7 +428,7 @@ namespace quest
if (guard_leader)
{
// 국고감소
// 국고감소
CMonarch::instance().SendtoDBDecMoney(money_need, ch->GetEmpire(), ch);
castle_save();
}
@ -491,7 +491,7 @@ namespace quest
return 0;
}
//군주 쿨타임 검사
//군주 쿨타임 검사
if (!ch->IsMCOK(CHARACTER::MI_WARP))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%d \xC3\xCA\xB0\xA3 \xC4\xF0\xC5\xB8\xC0\xD3\xC0\xCC \xC0\xFB\xBF\xEB\xC1\xDF\xC0\xD4\xB4\xCF\xB4\xD9."), ch->GetMCLTime(CHARACTER::MI_WARP));
@ -499,10 +499,10 @@ namespace quest
}
//군주 몹 소환 비용
//군주 몹 소환 비용
const int WarpPrice = 10000;
//군주 국고 검사
//군주 국고 검사
if (!CMonarch::instance().IsMoneyOk(WarpPrice, ch->GetEmpire()))
{
int NationMoney = CMonarch::instance().GetMoney(ch->GetEmpire());
@ -547,10 +547,10 @@ namespace quest
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s \xBF\xA1\xB0\xD4\xB7\xCE \xC0\xCC\xB5\xBF\xC7\xD5\xB4\xCF\xB4\xD9"), name.c_str());
ch->WarpSet(pos.x, pos.y);
//군주 돈 삭감
//군주 돈 삭감
CMonarch::instance().SendtoDBDecMoney(WarpPrice, ch->GetEmpire(), ch);
//쿨타임 초기화
//쿨타임 초기화
ch->SetMC(CHARACTER::MI_WARP);
}
@ -584,10 +584,10 @@ namespace quest
ch->WarpSet(x,y);
ch->Stop();
//군주 돈 삭감
//군주 돈 삭감
CMonarch::instance().SendtoDBDecMoney(WarpPrice, ch->GetEmpire(), ch);
//쿨타임 초기화
//쿨타임 초기화
ch->SetMC(CHARACTER::MI_WARP);
return 0;
@ -646,17 +646,17 @@ namespace quest
return 0;
}
// 군주 쿨타임 검사
// 군주 쿨타임 검사
if (!ch->IsMCOK(CHARACTER::MI_TRANSFER))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%d \xC3\xCA\xB0\xA3 \xC4\xF0\xC5\xB8\xC0\xD3\xC0\xCC \xC0\xFB\xBF\xEB\xC1\xDF\xC0\xD4\xB4\xCF\xB4\xD9."), ch->GetMCLTime(CHARACTER::MI_TRANSFER));
return 0;
}
// 군주 워프 비용
// 군주 워프 비용
const int WarpPrice = 10000;
// 군주 국고 검사
// 군주 국고 검사
if (!CMonarch::instance().IsMoneyOk(WarpPrice, ch->GetEmpire()))
{
int NationMoney = CMonarch::instance().GetMoney(ch->GetEmpire());
@ -705,10 +705,10 @@ namespace quest
P2P_MANAGER::instance().Send(&pgg, sizeof(TPacketGGTransfer));
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s \xB4\xD4\xC0\xBB \xBC\xD2\xC8\xAF\xC7\xCF\xBF\xB4\xBD\xC0\xB4\xCF\xB4\xD9."), name.c_str());
// 군주 돈 삭감
// 군주 돈 삭감
CMonarch::instance().SendtoDBDecMoney(WarpPrice, ch->GetEmpire(), ch);
// 쿨타임 초기화
// 쿨타임 초기화
ch->SetMC(CHARACTER::MI_TRANSFER);
}
else
@ -743,9 +743,9 @@ namespace quest
}
tch->WarpSet(ch->GetX(), ch->GetY(), ch->GetMapIndex());
// 군주 돈 삭감
// 군주 돈 삭감
CMonarch::instance().SendtoDBDecMoney(WarpPrice, ch->GetEmpire(), ch);
// 쿨타임 초기화
// 쿨타임 초기화
ch->SetMC(CHARACTER::MI_TRANSFER);
return 0;
}

View File

@ -323,8 +323,8 @@ namespace quest
}
};
// 파티 단위로 버프 주는 함수.
// 같은 맵에 있는 파티원만 영향을 받는다.
// 파티 단위로 버프 주는 함수.
// 같은 맵에 있는 파티원만 영향을 받는다.
int party_give_buff (lua_State* L)
{
CQuestManager & q = CQuestManager::instance();
@ -405,7 +405,7 @@ namespace quest
{ "is_in_dungeon", party_is_in_dungeon },
{ "give_buff", party_give_buff },
{ "is_map_member_flag_lt", party_is_map_member_flag_lt },
{ "get_member_pids", party_get_member_pids }, // 파티원들의 pid를 return
{ "get_member_pids", party_get_member_pids }, // 파티원들의 pid를 return
{ NULL, NULL }
};

View File

@ -232,7 +232,7 @@ namespace quest
return;
}
//PREVENT_PORTAL_AFTER_EXCHANGE
//교환 후 시간체크
//교환 후 시간체크
if ( iPulse - pkChr->GetExchangeTime() < PASSES_PER_SEC(60) )
{
pkChr->ChatPacket( CHAT_TYPE_INFO, LC_TEXT("\xB0\xC5\xB7\xA1 \xC8\xC4 1\xBA\xD0 \xC0\xCC\xB3\xBB\xBF\xA1\xB4\xC2 \xB4\xD9\xB8\xA5\xC1\xF6\xBF\xAA\xC0\xB8\xB7\xCE \xC0\xCC\xB5\xBF \xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9." ) );
@ -447,7 +447,7 @@ namespace quest
DWORD dwVnum;
if (lua_isnumber(L,2)) // 번호인경우 번호로 준다.
if (lua_isnumber(L,2)) // 번호인경우 번호로 준다.
dwVnum = (int) lua_tonumber(L, 2);
else if (!ITEM_MANAGER::instance().GetVnum(lua_tostring(L, 2), dwVnum))
{
@ -487,7 +487,7 @@ namespace quest
DWORD dwVnum;
if (lua_isnumber(L, 1)) // 번호인경우 번호로 준다.
if (lua_isnumber(L, 1)) // 번호인경우 번호로 준다.
{
dwVnum = (int) lua_tonumber(L, 1);
}
@ -543,7 +543,7 @@ namespace quest
DWORD dwVnum;
if (lua_isnumber(L, 1)) // 번호인경우 번호로 준다.
if (lua_isnumber(L, 1)) // 번호인경우 번호로 준다.
{
dwVnum = (int) lua_tonumber(L, 1);
}
@ -804,7 +804,7 @@ namespace quest
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
if (val > 0) // 증가시키는 것이므로 무조건 성공 리턴
if (val > 0) // 증가시키는 것이므로 무조건 성공 리턴
ch->PointChange(POINT_SP, val);
else if (val < 0)
{
@ -857,18 +857,18 @@ namespace quest
PC* pPC = CQuestManager::instance().GetCurrentPC();
LogManager::instance().QuestRewardLog(pPC->GetCurrentQuestName().c_str(), ch->GetPlayerID(), ch->GetLevel(), newLevel, 0);
//포인트 : 스킬, 서브스킬, 스탯
//포인트 : 스킬, 서브스킬, 스탯
ch->PointChange(POINT_SKILL, newLevel - ch->GetLevel());
ch->PointChange(POINT_SUB_SKILL, newLevel < 10 ? 0 : newLevel - std::max(ch->GetLevel(), 9));
ch->PointChange(POINT_STAT, ((std::clamp(newLevel, 1, 90) - ch->GetLevel()) * 3) + ch->GetPoint(POINT_LEVEL_STEP));
//레벨
//레벨
ch->PointChange(POINT_LEVEL, newLevel - ch->GetLevel(), false, true);
//HP, SP
ch->SetRandomHP((newLevel - 1) * Random::get(JobInitialPoints[ch->GetJob()].hp_per_lv_begin, JobInitialPoints[ch->GetJob()].hp_per_lv_end));
ch->SetRandomSP((newLevel - 1) * Random::get(JobInitialPoints[ch->GetJob()].sp_per_lv_begin, JobInitialPoints[ch->GetJob()].sp_per_lv_end));
// 회복
// 회복
ch->PointChange(POINT_HP, ch->GetMaxHP() - ch->GetHP());
ch->PointChange(POINT_SP, ch->GetMaxSP() - ch->GetSP());
@ -931,8 +931,8 @@ namespace quest
return 1;
}
// 20050725.myevan.은둔의 망토 사용중 혼석 수련시 선악치가 두배 소모되는 버그가 발생해
// 실제 선악치를 이용해 계산을 하게 한다.
// 20050725.myevan.은둔의 망토 사용중 혼석 수련시 선악치가 두배 소모되는 버그가 발생해
// 실제 선악치를 이용해 계산을 하게 한다.
int pc_get_real_alignment(lua_State* L)
{
lua_pushnumber(L, CQuestManager::instance().GetCurrentCharacterPtr()->GetRealAlignment()/10);
@ -1257,7 +1257,7 @@ namespace quest
ch->RemoveAffect(AFFECT_MOUNT);
ch->RemoveAffect(AFFECT_MOUNT_BONUS);
// 말이 소환되어 따라다니는 상태라면 말부터 없앰
// 말이 소환되어 따라다니는 상태라면 말부터 없앰
if (ch->GetHorse())
ch->HorseSummon(false);
@ -1525,7 +1525,7 @@ namespace quest
if (pct == 100 || Random::get(1, 100) <= pct)
{
// 개량 성공
// 개량 성공
lua_pushboolean(L, 1);
LPITEM pkNewItem = ITEM_MANAGER::instance().CreateItem(item->GetRefinedVnum(), 1, 0, false);
@ -1562,7 +1562,7 @@ namespace quest
}
else
{
// 개량 실패
// 개량 실패
lua_pushboolean(L, 0);
}
@ -1599,7 +1599,7 @@ namespace quest
pdw[1] = 1;
pdw[2] = q.GetEventFlag("lotto_round");
// 추첨서는 소켓을 설정한다
// 추첨서는 소켓을 설정한다
DBManager::instance().ReturnQuery(QID_LOTTO, ch->GetPlayerID(), pdw,
"INSERT INTO lotto_list VALUES(0, 'server%s', %u, NOW())",
get_table_postfix(), ch->GetPlayerID());
@ -1848,14 +1848,14 @@ namespace quest
return 0;
}
//텔레포트
//텔레포트
int pc_teleport ( lua_State * L )
{
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
int x=0,y=0;
if ( lua_isnumber(L, 1) )
{
// 지역명 워프
// 지역명 워프
const int TOWN_NUM = 10;
struct warp_by_town_name
{
@ -2056,13 +2056,13 @@ teleport_area:
int pc_change_name(lua_State* L)
{
// 리턴값
// 0: 새이름을 설정한 뒤 로그아웃을 안했음
// 1: 스크립트에서 문자열이 넘어오지 않았음
// 2: check_name 을 통과하지 못했음
// 3: 이미 같은 이름이 사용중
// 4: 성공
// 5: 해당 기능 지원하지 않음
// 리턴값
// 0: 새이름을 설정한 뒤 로그아웃을 안했음
// 1: 스크립트에서 문자열이 넘어오지 않았음
// 2: check_name 을 통과하지 못했음
// 3: 이미 같은 이름이 사용중
// 4: 성공
// 5: 해당 기능 지원하지 않음
if ( LC_IsEurope() )
{
lua_pushnumber(L, 5);
@ -2102,7 +2102,7 @@ teleport_area:
int count = 0;
str_to_number(count, row[0]);
// 이미 해당 이름을 가진 캐릭터가 있음
// 이미 해당 이름을 가진 캐릭터가 있음
if ( count != 0 )
{
lua_pushnumber(L, 3);
@ -2353,8 +2353,8 @@ teleport_area:
int idx = 1;
// 용혼석 슬롯은 할 필요 없을 듯.
// 이 함수는 탈석서용 함수인 듯 하다.
// 용혼석 슬롯은 할 필요 없을 듯.
// 이 함수는 탈석서용 함수인 듯 하다.
for ( int i=0; i < INVENTORY_MAX_NUM + WEAR_MAX_NUM; i++ )
{
LPITEM pItem = pChar->GetInventoryItem(i);
@ -2743,7 +2743,7 @@ teleport_area:
return 1;
}
int pc_get_informer_type(lua_State* L) //독일 선물 기능
int pc_get_informer_type(lua_State* L) //독일 선물 기능
{
LPCHARACTER pChar = CQuestManager::instance().GetCurrentCharacterPtr();
@ -2986,17 +2986,17 @@ teleport_area:
{ "charge_cash", pc_charge_cash },
{ "get_informer_type", pc_get_informer_type }, //독일 선물 기능
{ "get_informer_type", pc_get_informer_type }, //독일 선물 기능
{ "get_informer_item", pc_get_informer_item },
{ "give_award", pc_give_award }, //일본 계정당 한번씩 금괴 지급
{ "give_award_socket", pc_give_award_socket }, //몰 인벤토리에 아이템 지급. 소켓 설정을 위한 함수.
{ "give_award", pc_give_award }, //일본 계정당 한번씩 금괴 지급
{ "give_award_socket", pc_give_award_socket }, //몰 인벤토리에 아이템 지급. 소켓 설정을 위한 함수.
{ "get_killee_drop_pct", pc_get_killee_drop_pct }, /* mob_vnum.kill 이벤트에서 killee와 pc와의 level 차이, pc의 프리미엄 드랍률 등등을 고려한 아이템 드랍 확률.
* return (, ).
* ( , CreateDropItem의 GetDropPct의 iDeltaPercent, iRandRange를 return한다고 .)
* ( )
* : kill event에서만 !
{ "get_killee_drop_pct", pc_get_killee_drop_pct }, /* mob_vnum.kill 이벤트에서 killee와 pc와의 level 차이, pc의 프리미엄 드랍률 등등을 고려한 아이템 드랍 확률.
* return (, ).
* ( , CreateDropItem의 GetDropPct의 iDeltaPercent, iRandRange를 return한다고 .)
* ( )
* : kill event에서만 !
*/
{ NULL, NULL }

View File

@ -34,13 +34,13 @@ namespace quest
return 1;
}
// 소환수의 vnum
// 소환수의 vnum
DWORD mobVnum= lua_isnumber(L, 1) ? lua_tonumber(L, 1) : 0;
// 소환수의 이름
// 소환수의 이름
const char* petName = lua_isstring(L, 2) ? lua_tostring(L, 2) : 0;
// 소환하면 멀리서부터 달려오는지 여부
// 소환하면 멀리서부터 달려오는지 여부
bool bFromFar = lua_isboolean(L, 3) ? lua_toboolean(L, 3) : false;
CPetActor* pet = petSystem->Summon(mobVnum, pItem, petName, bFromFar);
@ -62,7 +62,7 @@ namespace quest
if (0 == petSystem)
return 0;
// 소환수의 vnum
// 소환수의 vnum
DWORD mobVnum= lua_isnumber(L, 1) ? lua_tonumber(L, 1) : 0;
petSystem->Unsummon(mobVnum);
@ -94,7 +94,7 @@ namespace quest
if (0 == petSystem)
return 0;
// 소환수의 vnum
// 소환수의 vnum
DWORD mobVnum= lua_isnumber(L, 1) ? lua_tonumber(L, 1) : 0;
CPetActor* petActor = petSystem->GetByVnum(mobVnum);

View File

@ -140,7 +140,7 @@ namespace quest
int quest_coroutine_yield(lua_State * L)
{
CQuestManager& q = CQuestManager::instance();
// other_pc_block 내부에서는 yield가 일어나서는 안된다. 절대로.
// other_pc_block 내부에서는 yield가 일어나서는 안된다. 절대로.
if (q.IsInOtherPCBlock())
{
quest_err("FATAL ERROR! Yield occur in other_pc_block.");
@ -214,10 +214,10 @@ namespace quest
{ "done", quest_done },
{ "getcurrentquestindex", quest_get_current_quest_index },
{ "no_send", quest_no_send },
// begin_other_pc_block(pid), end_other_pc_block 사이를 other_pc_block이라고 하자.
// other_pc_block에서는 current_pc가 pid로 변경된다.
// 끝나면 다시 원래의 current_pc로 돌아간다.
/* 이런 것을 위해 만듬.
// begin_other_pc_block(pid), end_other_pc_block 사이를 other_pc_block이라고 하자.
// other_pc_block에서는 current_pc가 pid로 변경된다.
// 끝나면 다시 원래의 current_pc로 돌아간다.
/* 이런 것을 위해 만듬.
for i, pid in next, pids, nil do
q.begin_other_pc_block(pid)
if pc.count_item(PASS_TICKET) < 1 then
@ -227,7 +227,7 @@ namespace quest
q.end_other_pc_block()
end
*/
// 주의 : other_pc_block 내부에서는 절대로 yield가 일어나서는 안된다.(ex. wait, select, input, ...)
// 주의 : other_pc_block 내부에서는 절대로 yield가 일어나서는 안된다.(ex. wait, select, input, ...)
{ "begin_other_pc_block", quest_begin_other_pc_block },
{ "end_other_pc_block", quest_end_other_pc_block },
{ NULL, NULL }

View File

@ -69,7 +69,7 @@ namespace quest
return 0;
}
// 현재 퀘스트에 등록된 타겟을 삭제 한다.
// 현재 퀘스트에 등록된 타겟을 삭제 한다.
int target_delete(lua_State* L)
{
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
@ -86,7 +86,7 @@ namespace quest
return 0;
}
// 현재 퀘스트 인덱스로 되어있는 타겟을 모두 삭제한다.
// 현재 퀘스트 인덱스로 되어있는 타겟을 모두 삭제한다.
int target_clear(lua_State* L)
{
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();

View File

@ -57,29 +57,29 @@ namespace quest
m_pSelectedDungeon = NULL;
m_mapEventName.insert(TEventNameMap::value_type("click", QUEST_CLICK_EVENT)); // NPC를 클릭
m_mapEventName.insert(TEventNameMap::value_type("kill", QUEST_KILL_EVENT)); // Mob을 사냥
m_mapEventName.insert(TEventNameMap::value_type("timer", QUEST_TIMER_EVENT)); // 미리 지정해둔 시간이 지남
m_mapEventName.insert(TEventNameMap::value_type("levelup", QUEST_LEVELUP_EVENT)); // 레벨업을 함
m_mapEventName.insert(TEventNameMap::value_type("login", QUEST_LOGIN_EVENT)); // 로그인 시
m_mapEventName.insert(TEventNameMap::value_type("logout", QUEST_LOGOUT_EVENT)); // 로그아웃 시
m_mapEventName.insert(TEventNameMap::value_type("button", QUEST_BUTTON_EVENT)); // 퀘스트 버튼을 누름
m_mapEventName.insert(TEventNameMap::value_type("info", QUEST_INFO_EVENT)); // 퀘스트 정보창을 염
m_mapEventName.insert(TEventNameMap::value_type("chat", QUEST_CHAT_EVENT)); // 특정 키워드로 대화를 함
m_mapEventName.insert(TEventNameMap::value_type("in", QUEST_ATTR_IN_EVENT)); // 맵의 특정 속성에 들어감
m_mapEventName.insert(TEventNameMap::value_type("out", QUEST_ATTR_OUT_EVENT)); // 맵의 특정 속성에서 나옴
m_mapEventName.insert(TEventNameMap::value_type("use", QUEST_ITEM_USE_EVENT)); // 퀘스트 아이템을 사용
m_mapEventName.insert(TEventNameMap::value_type("server_timer", QUEST_SERVER_TIMER_EVENT)); // 서버 타이머 (아직 테스트 안됐음)
m_mapEventName.insert(TEventNameMap::value_type("enter", QUEST_ENTER_STATE_EVENT)); // 현재 스테이트가 됨
m_mapEventName.insert(TEventNameMap::value_type("leave", QUEST_LEAVE_STATE_EVENT)); // 현재 스테이트에서 다른 스테이트로 바뀜
m_mapEventName.insert(TEventNameMap::value_type("letter", QUEST_LETTER_EVENT)); // 로긴 하거나 스테이트가 바껴 새로 정보를 세팅해줘야함
m_mapEventName.insert(TEventNameMap::value_type("take", QUEST_ITEM_TAKE_EVENT)); // 아이템을 받음
m_mapEventName.insert(TEventNameMap::value_type("target", QUEST_TARGET_EVENT)); // 타겟
m_mapEventName.insert(TEventNameMap::value_type("party_kill", QUEST_PARTY_KILL_EVENT)); // 파티 멤버가 몬스터를 사냥 (리더에게 옴)
m_mapEventName.insert(TEventNameMap::value_type("click", QUEST_CLICK_EVENT)); // NPC를 클릭
m_mapEventName.insert(TEventNameMap::value_type("kill", QUEST_KILL_EVENT)); // Mob을 사냥
m_mapEventName.insert(TEventNameMap::value_type("timer", QUEST_TIMER_EVENT)); // 미리 지정해둔 시간이 지남
m_mapEventName.insert(TEventNameMap::value_type("levelup", QUEST_LEVELUP_EVENT)); // 레벨업을 함
m_mapEventName.insert(TEventNameMap::value_type("login", QUEST_LOGIN_EVENT)); // 로그인 시
m_mapEventName.insert(TEventNameMap::value_type("logout", QUEST_LOGOUT_EVENT)); // 로그아웃 시
m_mapEventName.insert(TEventNameMap::value_type("button", QUEST_BUTTON_EVENT)); // 퀘스트 버튼을 누름
m_mapEventName.insert(TEventNameMap::value_type("info", QUEST_INFO_EVENT)); // 퀘스트 정보창을 염
m_mapEventName.insert(TEventNameMap::value_type("chat", QUEST_CHAT_EVENT)); // 특정 키워드로 대화를 함
m_mapEventName.insert(TEventNameMap::value_type("in", QUEST_ATTR_IN_EVENT)); // 맵의 특정 속성에 들어감
m_mapEventName.insert(TEventNameMap::value_type("out", QUEST_ATTR_OUT_EVENT)); // 맵의 특정 속성에서 나옴
m_mapEventName.insert(TEventNameMap::value_type("use", QUEST_ITEM_USE_EVENT)); // 퀘스트 아이템을 사용
m_mapEventName.insert(TEventNameMap::value_type("server_timer", QUEST_SERVER_TIMER_EVENT)); // 서버 타이머 (아직 테스트 안됐음)
m_mapEventName.insert(TEventNameMap::value_type("enter", QUEST_ENTER_STATE_EVENT)); // 현재 스테이트가 됨
m_mapEventName.insert(TEventNameMap::value_type("leave", QUEST_LEAVE_STATE_EVENT)); // 현재 스테이트에서 다른 스테이트로 바뀜
m_mapEventName.insert(TEventNameMap::value_type("letter", QUEST_LETTER_EVENT)); // 로긴 하거나 스테이트가 바껴 새로 정보를 세팅해줘야함
m_mapEventName.insert(TEventNameMap::value_type("take", QUEST_ITEM_TAKE_EVENT)); // 아이템을 받음
m_mapEventName.insert(TEventNameMap::value_type("target", QUEST_TARGET_EVENT)); // 타겟
m_mapEventName.insert(TEventNameMap::value_type("party_kill", QUEST_PARTY_KILL_EVENT)); // 파티 멤버가 몬스터를 사냥 (리더에게 옴)
m_mapEventName.insert(TEventNameMap::value_type("unmount", QUEST_UNMOUNT_EVENT));
m_mapEventName.insert(TEventNameMap::value_type("pick", QUEST_ITEM_PICK_EVENT)); // 떨어져있는 아이템을 습득함.
m_mapEventName.insert(TEventNameMap::value_type("sig_use", QUEST_SIG_USE_EVENT)); // Special item group에 속한 아이템을 사용함.
m_mapEventName.insert(TEventNameMap::value_type("item_informer", QUEST_ITEM_INFORMER_EVENT)); // 독일선물기능테스트
m_mapEventName.insert(TEventNameMap::value_type("pick", QUEST_ITEM_PICK_EVENT)); // 떨어져있는 아이템을 습득함.
m_mapEventName.insert(TEventNameMap::value_type("sig_use", QUEST_SIG_USE_EVENT)); // Special item group에 속한 아이템을 사용함.
m_mapEventName.insert(TEventNameMap::value_type("item_informer", QUEST_ITEM_INFORMER_EVENT)); // 독일선물기능테스트
m_bNoSend = false;
@ -253,9 +253,9 @@ namespace quest
if (!pPC->GetRunningQuestState()->chat_scripts.empty())
{
// 채팅 이벤트인 경우
// 현재 퀘스트는 어느 퀘스트를 실행할 것인가를 고르는 퀘스트 이므로
// 끝내고 선택된 퀘스트를 실행한다.
// 채팅 이벤트인 경우
// 현재 퀘스트는 어느 퀘스트를 실행할 것인가를 고르는 퀘스트 이므로
// 끝내고 선택된 퀘스트를 실행한다.
QuestState& old_qs = *pPC->GetRunningQuestState();
CloseState(old_qs);
@ -368,7 +368,7 @@ namespace quest
pPC->CancelRunning();
}
// 지우기 전에 로그아웃 한다.
// 지우기 전에 로그아웃 한다.
Logout(ch->GetPlayerID());
if (ch == m_pCurrentCharacter)
@ -380,7 +380,7 @@ namespace quest
///////////////////////////////////////////////////////////////////////////////////////////
//
// Quest Event 관련
// Quest Event 관련
//
///////////////////////////////////////////////////////////////////////////////////////////
void CQuestManager::Login(unsigned int pc, const char * c_pszQuest)
@ -427,9 +427,9 @@ namespace quest
if (!CheckQuestLoaded(pPC))
return;
/* [hyo] 몹 kill시 중복 카운팅 이슈 관련한 수정사항
quest script에 when 171.kill begin ...
return하지 . (2011/07/21)
/* [hyo] 몹 kill시 중복 카운팅 이슈 관련한 수정사항
quest script에 when 171.kill begin ...
return하지 . (2011/07/21)
*/
// call script
m_mapNPC[npc].OnKill(*pPC);
@ -684,7 +684,7 @@ namespace quest
}
}
// Speical Item Group에 정의된 Group Use
// Speical Item Group에 정의된 Group Use
bool CQuestManager::SIGUse(unsigned int pc, DWORD sig_vnum, LPITEM item, bool bReceiveAll)
{
SPDLOG_TRACE("questmanager::SIGUse Start : itemVnum : {} PC : {}", item->GetOriginalVnum(), pc);
@ -826,7 +826,7 @@ namespace quest
else
SPDLOG_ERROR("QUEST no such pc id : {}", pc);
}
//독일 선물 기능 테스트
//독일 선물 기능 테스트
void CQuestManager::ItemInformer(unsigned int pc,unsigned int vnum)
{
@ -836,7 +836,7 @@ namespace quest
m_mapNPC[QUEST_NO_NPC].OnItemInformer(*pPC,vnum);
}
///////////////////////////////////////////////////////////////////////////////////////////
// END OF 퀘스트 이벤트 처리
// END OF 퀘스트 이벤트 처리
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
@ -1258,19 +1258,19 @@ namespace quest
continue;
if (value)
{
// 밤
// 밤
ch->ChatPacket(CHAT_TYPE_COMMAND, "DayMode dark");
}
else
{
// 낮
// 낮
ch->ChatPacket(CHAT_TYPE_COMMAND, "DayMode light");
}
}
if (value && !prev_value)
{
// 없으면 만들어준다
// 없으면 만들어준다
struct SNPCSellFireworkPosition
{
int lMapIndex;
@ -1306,7 +1306,7 @@ namespace quest
}
else if (!value && prev_value)
{
// 있으면 지워준다
// 있으면 지워준다
CharacterVectorInteractor i;
if (CHARACTER_MANAGER::instance().GetCharactersByRaceNum(xmas::MOB_XMAS_FIRWORK_SELLER_VNUM, i))
@ -1395,7 +1395,7 @@ namespace quest
}
else if (name == "new_xmas_event")
{
// 20126 new산타.
// 20126 new산타.
static DWORD new_santa = 20126;
if (value != 0)
{
@ -1534,12 +1534,12 @@ namespace quest
bool CQuestManager::ExecuteQuestScript(PC& pc, const string& quest_name, const int state, const char* code, const int code_size, vector<AArgScript*>* pChatScripts, bool bUseCache)
{
// 실행공간을 생성
// 실행공간을 생성
QuestState qs = CQuestManager::instance().OpenState(quest_name, state);
if (pChatScripts)
qs.chat_scripts.swap(*pChatScripts);
// 코드를 읽어들임
// 코드를 읽어들임
if (bUseCache)
{
lua_getglobal(qs.co, "__codecache");
@ -1578,10 +1578,10 @@ namespace quest
else
luaL_loadbuffer(qs.co, code, code_size, quest_name.c_str());
// 플레이어와 연결
// 플레이어와 연결
pc.SetQuest(quest_name, qs);
// 실행
// 실행
QuestState& rqs = *pc.GetRunningQuestState();
if (!CQuestManager::instance().RunState(rqs))
{

View File

@ -131,7 +131,7 @@ namespace quest
//
///////////////////////////////////////////////////////////////////////////
// 순서 Index (여러개 있을 수 있으므로 있는 것임, 실제 index 값은 쓰지 않음)
// 순서 Index (여러개 있을 수 있으므로 있는 것임, 실제 index 값은 쓰지 않음)
j = i;
i = s.find('.', i + 1);
@ -410,7 +410,7 @@ namespace quest
void operator()(PC::QuestInfoIterator& itPCQuest, NPC::QuestMapType::iterator& itQuestMap)
{
// 없으니 새로 시작
// 없으니 새로 시작
DWORD dwQuestIndex = itQuestMap->first;
if (NPC::HasStartState(itQuestMap->second) && CQuestManager::instance().CanStartQuest(dwQuestIndex))
@ -494,8 +494,8 @@ namespace quest
for (int i = 0; i < fMatch.size; i++)
{
if ( i != 0 ) {
//2012.05.14 <김용욱> : 퀘스트 매니저의 m_pCurrentPC가 바뀌는 경우가 발생하여,
//두개 이상의 스크립트를 실행시, 두번째 부터는 퀘스트 매니저의 PC 값을 새로 셋팅한다.
//2012.05.14 <김용욱> : 퀘스트 매니저의 m_pCurrentPC가 바뀌는 경우가 발생하여,
//두개 이상의 스크립트를 실행시, 두번째 부터는 퀘스트 매니저의 PC 값을 새로 셋팅한다.
PC * pPC = CQuestManager::instance().GetPC(pc.GetID());
}
@ -805,7 +805,7 @@ namespace quest
QuestMapType & rmapEventOwnQuest = m_mapOwnQuest[EventIndex];
QuestMapType::iterator itQuestMap = rmapEventOwnQuest.find(quest_index);
// 그런 퀘스트가 없음
// 그런 퀘스트가 없음
if (itQuestMap == rmapEventOwnQuest.end())
return false;
@ -817,7 +817,7 @@ namespace quest
}
else
{
// 새로 시작할까요?
// 새로 시작할까요?
if (CQuestManager::instance().CanStartQuest(itQuestMap->first, pc) && HasStartState(itQuestMap->second))
iState = 0;
else
@ -962,7 +962,7 @@ namespace quest
else
return HandleEvent(pc, QUEST_ITEM_PICK_EVENT);
}
//독일 선물 기능 테스트
//독일 선물 기능 테스트
bool NPC::OnItemInformer(PC& pc, unsigned int vnum)
{
return HandleEvent(pc, QUEST_ITEM_INFORMER_EVENT);

View File

@ -307,10 +307,10 @@ namespace quest
{
LPCHARACTER npc = CQuestManager::instance().GetCurrentNPCCharacterPtr();
LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
// npc 있었던 경우
// npc 있었던 경우
if (npc && !npc->IsPC())
{
// 그 엔피씨가 나에게 락인 경우
// 그 엔피씨가 나에게 락인 경우
if (ch->GetPlayerID() == npc->GetQuestNPCID())
{
npc->SetQuestNPCID(0);

View File

@ -24,7 +24,7 @@ enum ERegenModes
MODE_VNUM
};
static bool get_word(FILE *fp, char *buf) // 워드단위로 받는다.
static bool get_word(FILE *fp, char *buf) // 워드단위로 받는다.
{
int i = 0;
int c;
@ -172,7 +172,7 @@ static bool read_line(FILE *fp, LPREGEN regen)
case MODE_Z_SECTION:
str_to_number(regen->z_section, szTmp);
// 익셉션 이면 나가주자.
// 익셉션 이면 나가주자.
if (regen->type == REGEN_TYPE_EXCEPTION)
return true;
@ -500,7 +500,7 @@ bool regen_do(const char* filename, int lMapIndex, int base_x, int base_y, LPDUN
// before the call to CHARACTER::SetRegen()
}
// 처음엔 무조건 리젠 해준다.
// 처음엔 무조건 리젠 해준다.
regen_spawn_dungeon(regen, pDungeon, bOnce);
}
@ -576,7 +576,7 @@ bool regen_load_in_file(const char* filename, int lMapIndex, int base_x, int bas
}
}
// 처음엔 무조건 리젠 해준다.
// 처음엔 무조건 리젠 해준다.
regen_spawn(regen, true);
}
}
@ -683,11 +683,11 @@ bool regen_load(const char* filename, int lMapIndex, int base_x, int base_y)
}
//NO_REGEN
// Desc: regen.txt (외 리젠관련 텍스트 ) 에서 리젠 시간을 0으로 세팅할시
// 리젠을 하지 안한다.
// Desc: regen.txt (외 리젠관련 텍스트 ) 에서 리젠 시간을 0으로 세팅할시
// 리젠을 하지 안한다.
if (regen->time != 0)
{
// 처음엔 무조건 리젠 해준다.
// 처음엔 무조건 리젠 해준다.
regen_spawn(regen, false);
regen_event_info* info = AllocEventInfo<regen_event_info>();
@ -752,14 +752,14 @@ void regen_reset(int x, int y)
if (!regen->event)
continue;
// 좌표가 있으면 좌표 내에 있는 리젠 리스트만 리젠 시킨다.
// 좌표가 있으면 좌표 내에 있는 리젠 리스트만 리젠 시킨다.
if (x != 0 || y != 0)
{
if (x >= regen->sx && x <= regen->ex)
if (y >= regen->sy && y <= regen->ey)
event_reset_time(regen->event, 1);
}
// 없으면 전부 리젠
// 없으면 전부 리젠
else
event_reset_time(regen->event, 1);
}

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