forked from metin2/server
convert comments to utf-8
This commit is contained in:
parent
4a1460f36e
commit
eacc808366
|
@ -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>();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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 },
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Filename: queue.c
|
||||
* Description: 큐 처리
|
||||
* Description: 큐 처리
|
||||
*
|
||||
* Author: 김한주 (aka. 비엽, Cronan), 송영진 (aka. myevan, 빗자루)
|
||||
* Author: 김한주 (aka. 비엽, Cronan), 송영진 (aka. myevan, 빗자루)
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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 호출
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -48,7 +48,7 @@ const char *quote_find_end(const char *string)
|
|||
{
|
||||
if (quote && *tmp == '\\' && *(tmp + 1))
|
||||
{
|
||||
// \ 다음 문자가 " 면 스킵한다.
|
||||
// \ 다음 문자가 " 면 스킵한다.
|
||||
switch (*(tmp + 1))
|
||||
{
|
||||
case '"':
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -437,7 +437,7 @@ namespace quest
|
|||
ITEM_MANAGER::instance().FlushDelayedSave(pkNewItem);
|
||||
pkNewItem->AttrLog();
|
||||
|
||||
// 성공!
|
||||
// 성공!
|
||||
lua_pushboolean(L, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ namespace quest
|
|||
}
|
||||
if (pMarriage->pWeddingInfo)
|
||||
{
|
||||
// 결혼식 끝내기 요청
|
||||
// 결혼식 끝내기 요청
|
||||
pMarriage->RequestEndWedding();
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue