1
0
forked from metin2/server
server/src/game/src/input_main.cpp

3342 lines
94 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stdafx.h"
#include "constants.h"
#include "config.h"
#include "utils.h"
#include "desc_client.h"
#include "desc_manager.h"
#include "buffer_manager.h"
#include "packet.h"
#include "protocol.h"
#include "char.h"
#include "char_manager.h"
#include "item.h"
#include "item_manager.h"
#include "cmd.h"
#include "shop.h"
#include "shop_manager.h"
#include "safebox.h"
#include "regen.h"
#include "battle.h"
#include "exchange.h"
#include "questmanager.h"
#include "profiler.h"
#include "messenger_manager.h"
#include "party.h"
#include "p2p.h"
#include "affect.h"
#include "guild.h"
#include "guild_manager.h"
#include "log.h"
#include "banword.h"
#include "empire_text_convert.h"
#include "unique_item.h"
#include "building.h"
#include "locale_service.h"
#include "gm.h"
#include "spam.h"
#include "ani.h"
#include "motion.h"
#include "OXEvent.h"
#include "locale_service.h"
#include "DragonSoul.h"
extern void SendShout(const char * szText, BYTE bEmpire);
extern int g_nPortalLimitTime;
static int __deposit_limit()
{
return (1000*10000); // 1õ¸¸
}
void SendBlockChatInfo(LPCHARACTER ch, int sec)
{
if (sec <= 0)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xC3\xA4\xC6\xC3 \xB1\xDD\xC1\xF6 \xBB\xF3\xC5\xC2\xC0\xD4\xB4\xCF\xB4\xD9."));
return;
}
int hour = sec / 3600;
sec -= hour * 3600;
int min = (sec / 60);
sec -= min * 60;
char buf[128+1];
if (hour > 0 && min > 0)
snprintf(buf, sizeof(buf), LC_TEXT("%d \xBD\xC3\xB0\xA3 %d \xBA\xD0 %d \xC3\xCA \xB5\xBF\xBE\xC8 \xC3\xA4\xC6\xC3\xB1\xDD\xC1\xF6 \xBB\xF3\xC5\xC2\xC0\xD4\xB4\xCF\xB4\xD9"), hour, min, sec);
else if (hour > 0 && min == 0)
snprintf(buf, sizeof(buf), LC_TEXT("%d \xBD\xC3\xB0\xA3 %d \xC3\xCA \xB5\xBF\xBE\xC8 \xC3\xA4\xC6\xC3\xB1\xDD\xC1\xF6 \xBB\xF3\xC5\xC2\xC0\xD4\xB4\xCF\xB4\xD9"), hour, sec);
else if (hour == 0 && min > 0)
snprintf(buf, sizeof(buf), LC_TEXT("%d \xBA\xD0 %d \xC3\xCA \xB5\xBF\xBE\xC8 \xC3\xA4\xC6\xC3\xB1\xDD\xC1\xF6 \xBB\xF3\xC5\xC2\xC0\xD4\xB4\xCF\xB4\xD9"), min, sec);
else
snprintf(buf, sizeof(buf), LC_TEXT("%d \xC3\xCA \xB5\xBF\xBE\xC8 \xC3\xA4\xC6\xC3\xB1\xDD\xC1\xF6 \xBB\xF3\xC5\xC2\xC0\xD4\xB4\xCF\xB4\xD9"), sec);
ch->ChatPacket(CHAT_TYPE_INFO, buf);
}
EVENTINFO(spam_event_info)
{
char host[MAX_HOST_LENGTH+1];
spam_event_info()
{
::memset( host, 0, MAX_HOST_LENGTH+1 );
}
};
typedef std::unordered_map<std::string, std::pair<unsigned int, LPEVENT> > spam_score_of_ip_t;
spam_score_of_ip_t spam_score_of_ip;
EVENTFUNC(block_chat_by_ip_event)
{
spam_event_info* info = dynamic_cast<spam_event_info*>( event->info );
if ( info == NULL )
{
SPDLOG_ERROR("block_chat_by_ip_event> <Factor> Null pointer" );
return 0;
}
const char * host = info->host;
spam_score_of_ip_t::iterator it = spam_score_of_ip.find(host);
if (it != spam_score_of_ip.end())
{
it->second.first = 0;
it->second.second = NULL;
}
return 0;
}
bool SpamBlockCheck(LPCHARACTER ch, const char* const buf, const size_t buflen)
{
extern int g_iSpamBlockMaxLevel;
if (ch->GetLevel() < g_iSpamBlockMaxLevel)
{
spam_score_of_ip_t::iterator it = spam_score_of_ip.find(ch->GetDesc()->GetHostName());
if (it == spam_score_of_ip.end())
{
spam_score_of_ip.insert(std::make_pair(ch->GetDesc()->GetHostName(), std::make_pair(0, (LPEVENT) NULL)));
it = spam_score_of_ip.find(ch->GetDesc()->GetHostName());
}
if (it->second.second)
{
SendBlockChatInfo(ch, event_time(it->second.second) / passes_per_sec);
return true;
}
unsigned int score;
const char * word = SpamManager::instance().GetSpamScore(buf, buflen, score);
it->second.first += score;
if (word)
SPDLOG_DEBUG("SPAM_SCORE: {} text: {} score: {} total: {} word: {}", ch->GetName(), buf, score, it->second.first, word);
extern unsigned int g_uiSpamBlockScore;
extern unsigned int g_uiSpamBlockDuration;
if (it->second.first >= g_uiSpamBlockScore)
{
spam_event_info* info = AllocEventInfo<spam_event_info>();
strlcpy(info->host, ch->GetDesc()->GetHostName(), sizeof(info->host));
it->second.second = event_create(block_chat_by_ip_event, info, PASSES_PER_SEC(g_uiSpamBlockDuration));
SPDLOG_DEBUG("SPAM_IP: {} for {} seconds", info->host, g_uiSpamBlockDuration);
LogManager::instance().CharLog(ch, 0, "SPAM", word);
SendBlockChatInfo(ch, event_time(it->second.second) / passes_per_sec);
return true;
}
}
return false;
}
enum
{
TEXT_TAG_PLAIN,
TEXT_TAG_TAG, // ||
TEXT_TAG_COLOR, // |cffffffff
TEXT_TAG_HYPERLINK_START, // |H
TEXT_TAG_HYPERLINK_END, // |h ex) |Hitem:1234:1:1:1|h
TEXT_TAG_RESTORE_COLOR,
};
int GetTextTag(const char * src, int maxLen, int & tagLen, std::string & extraInfo)
{
tagLen = 1;
if (maxLen < 2 || *src != '|')
return TEXT_TAG_PLAIN;
const char * cur = ++src;
if (*cur == '|') // ||´Â |·Î Ç¥½ÃÇÑ´Ù.
{
tagLen = 2;
return TEXT_TAG_TAG;
}
else if (*cur == 'c') // color |cffffffffblahblah|r
{
tagLen = 2;
return TEXT_TAG_COLOR;
}
else if (*cur == 'H') // hyperlink |Hitem:10000:0:0:0:0|h[À̸§]|h
{
tagLen = 2;
return TEXT_TAG_HYPERLINK_START;
}
else if (*cur == 'h') // end of hyperlink
{
tagLen = 2;
return TEXT_TAG_HYPERLINK_END;
}
return TEXT_TAG_PLAIN;
}
void GetTextTagInfo(const char * src, int src_len, int & hyperlinks, bool & colored)
{
colored = false;
hyperlinks = 0;
int len;
std::string extraInfo;
for (int i = 0; i < src_len;)
{
int tag = GetTextTag(&src[i], src_len - i, len, extraInfo);
if (tag == TEXT_TAG_HYPERLINK_START)
++hyperlinks;
if (tag == TEXT_TAG_COLOR)
colored = true;
i += len;
}
}
int ProcessTextTag(LPCHARACTER ch, const char * c_pszText, size_t len)
{
//2012.05.17 ±è¿ë¿í
//0 : Á¤»óÀûÀ¸·Î »ç¿ë
//1 : ±Ý°­°æ ºÎÁ·
//2 : ±Ý°­°æÀÌ ÀÖÀ¸³ª, °³ÀλóÁ¡¿¡¼­ »ç¿ëÁß
//3 : ±³È¯Áß
//4 : ¿¡·¯
int hyperlinks;
bool colored;
GetTextTagInfo(c_pszText, len, hyperlinks, colored);
if (colored == true && hyperlinks == 0)
return 4;
if (ch->GetExchange())
{
if (hyperlinks == 0)
return 0;
else
return 3;
}
int nPrismCount = ch->CountSpecifyItem(ITEM_PRISM);
if (nPrismCount < hyperlinks)
return 1;
if (!ch->GetMyShop())
{
ch->RemoveSpecifyItem(ITEM_PRISM, hyperlinks);
return 0;
} else
{
int sellingNumber = ch->GetMyShop()->GetNumberByVnum(ITEM_PRISM);
if(nPrismCount - sellingNumber < hyperlinks)
{
return 2;
} else
{
ch->RemoveSpecifyItem(ITEM_PRISM, hyperlinks);
return 0;
}
}
return 4;
}
int CInputMain::Whisper(LPCHARACTER ch, const char * data, size_t uiBytes)
{
const TPacketCGWhisper* pinfo = reinterpret_cast<const TPacketCGWhisper*>(data);
if (uiBytes < pinfo->wSize)
return -1;
int iExtraLen = pinfo->wSize - sizeof(TPacketCGWhisper);
if (iExtraLen < 0)
{
SPDLOG_ERROR("invalid packet length (len {} size {} buffer {})", iExtraLen, pinfo->wSize, uiBytes);
ch->GetDesc()->SetPhase(PHASE_CLOSE);
return -1;
}
if (ch->FindAffect(AFFECT_BLOCK_CHAT))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xC3\xA4\xC6\xC3 \xB1\xDD\xC1\xF6 \xBB\xF3\xC5\xC2\xC0\xD4\xB4\xCF\xB4\xD9."));
return (iExtraLen);
}
LPCHARACTER pkChr = CHARACTER_MANAGER::instance().FindPC(pinfo->szNameTo);
if (pkChr == ch)
return (iExtraLen);
LPDESC pkDesc = NULL;
BYTE bOpponentEmpire = 0;
if (test_server)
{
if (!pkChr)
SPDLOG_DEBUG("Whisper to {}({}) from {}", "Null", pinfo->szNameTo, ch->GetName());
else
SPDLOG_DEBUG("Whisper to {}({}) from {}", pkChr->GetName(), pinfo->szNameTo, ch->GetName());
}
if (ch->IsBlockMode(BLOCK_WHISPER))
{
if (ch->GetDesc())
{
TPacketGCWhisper pack;
pack.bHeader = HEADER_GC_WHISPER;
pack.bType = WHISPER_TYPE_SENDER_BLOCKED;
pack.wSize = sizeof(TPacketGCWhisper);
strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
ch->GetDesc()->Packet(&pack, sizeof(pack));
}
return iExtraLen;
}
if (!pkChr)
{
CCI * pkCCI = P2P_MANAGER::instance().Find(pinfo->szNameTo);
if (pkCCI)
{
pkDesc = pkCCI->pkDesc;
pkDesc->SetRelay(pinfo->szNameTo);
bOpponentEmpire = pkCCI->bEmpire;
SPDLOG_TRACE("Whisper to {} from {} (Channel {} Mapindex {})", "Null", ch->GetName(), pkCCI->bChannel, pkCCI->lMapIndex);
}
}
else
{
pkDesc = pkChr->GetDesc();
bOpponentEmpire = pkChr->GetEmpire();
}
if (!pkDesc)
{
if (ch->GetDesc())
{
TPacketGCWhisper pack;
pack.bHeader = HEADER_GC_WHISPER;
pack.bType = WHISPER_TYPE_NOT_EXIST;
pack.wSize = sizeof(TPacketGCWhisper);
strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
ch->GetDesc()->Packet(&pack, sizeof(TPacketGCWhisper));
SPDLOG_DEBUG("WHISPER: no player");
}
}
else
{
if (ch->IsBlockMode(BLOCK_WHISPER))
{
if (ch->GetDesc())
{
TPacketGCWhisper pack;
pack.bHeader = HEADER_GC_WHISPER;
pack.bType = WHISPER_TYPE_SENDER_BLOCKED;
pack.wSize = sizeof(TPacketGCWhisper);
strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
ch->GetDesc()->Packet(&pack, sizeof(pack));
}
}
else if (pkChr && pkChr->IsBlockMode(BLOCK_WHISPER))
{
if (ch->GetDesc())
{
TPacketGCWhisper pack;
pack.bHeader = HEADER_GC_WHISPER;
pack.bType = WHISPER_TYPE_TARGET_BLOCKED;
pack.wSize = sizeof(TPacketGCWhisper);
strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
ch->GetDesc()->Packet(&pack, sizeof(pack));
}
}
else
{
BYTE bType = WHISPER_TYPE_NORMAL;
char buf[CHAT_MAX_LEN + 1];
strlcpy(buf, data + sizeof(TPacketCGWhisper), std::min<size_t>(iExtraLen + 1, sizeof(buf)));
const size_t buflen = strlen(buf);
if (true == SpamBlockCheck(ch, buf, buflen))
{
if (!pkChr)
{
CCI * pkCCI = P2P_MANAGER::instance().Find(pinfo->szNameTo);
if (pkCCI)
{
pkDesc->SetRelay("");
}
}
return iExtraLen;
}
if (LC_IsCanada() == false)
{
CBanwordManager::instance().ConvertString(buf, buflen);
}
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 (!pkChr)
{
// ´Ù¸¥ ¼­¹ö¿¡ ÀÖÀ¸´Ï Á¦±¹ Ç¥½Ã¸¸ ÇÑ´Ù. bTypeÀÇ »óÀ§ 4ºñÆ®¸¦ Empire¹øÈ£·Î »ç¿ëÇÑ´Ù.
bType = ch->GetEmpire() << 4;
}
else
{
ConvertEmpireText(ch->GetEmpire(), buf, buflen, 10 + 2 * pkChr->GetSkillPower(SKILL_LANGUAGE1 + ch->GetEmpire() - 1)/*º¯È¯È®·ü*/);
}
}
int processReturn = ProcessTextTag(ch, buf, buflen);
if (0!=processReturn)
{
if (ch->GetDesc())
{
TItemTable * pTable = ITEM_MANAGER::instance().GetTable(ITEM_PRISM);
if (pTable)
{
char buf[128];
int len;
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);
if (len < 0 || len >= (int) sizeof(buf))
len = sizeof(buf) - 1;
++len; // \0 ¹®ÀÚ Æ÷ÇÔ
TPacketGCWhisper pack;
pack.bHeader = HEADER_GC_WHISPER;
pack.bType = WHISPER_TYPE_ERROR;
pack.wSize = sizeof(TPacketGCWhisper) + len;
strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
ch->GetDesc()->RawPacket(&pack, sizeof(pack));
ch->GetDesc()->Packet(buf, len);
SPDLOG_DEBUG("WHISPER: not enough {}: char: {}", pTable->szLocaleName, ch->GetName());
}
}
// ¸±·¡ÀÌ »óÅÂÀÏ ¼ö ÀÖÀ¸¹Ç·Î ¸±·¡À̸¦ Ç®¾îÁØ´Ù.
pkDesc->SetRelay("");
return (iExtraLen);
}
if (ch->IsGM())
bType = (bType & 0xF0) | WHISPER_TYPE_GM;
if (buflen > 0)
{
TPacketGCWhisper pack;
pack.bHeader = HEADER_GC_WHISPER;
pack.wSize = sizeof(TPacketGCWhisper) + buflen;
pack.bType = bType;
strlcpy(pack.szNameFrom, ch->GetName(), sizeof(pack.szNameFrom));
// desc->BufferedPacketÀ» ÇÏÁö ¾Ê°í ¹öÆÛ¿¡ ½á¾ßÇÏ´Â ÀÌÀ¯´Â
// P2P relayµÇ¾î ÆÐŶÀÌ Ä¸½¶È­ µÉ ¼ö Àֱ⠶§¹®ÀÌ´Ù.
TEMP_BUFFER tmpbuf;
tmpbuf.write(&pack, sizeof(pack));
tmpbuf.write(buf, buflen);
pkDesc->Packet(tmpbuf.read_peek(), tmpbuf.size());
if (LC_IsEurope() != true)
{
SPDLOG_DEBUG("WHISPER: {} -> {} : {}", ch->GetName(), pinfo->szNameTo, buf);
}
}
}
}
if(pkDesc)
pkDesc->SetRelay("");
return (iExtraLen);
}
struct RawPacketToCharacterFunc
{
const void * m_buf;
int m_buf_len;
RawPacketToCharacterFunc(const void * buf, int buf_len) : m_buf(buf), m_buf_len(buf_len)
{
}
void operator () (LPCHARACTER c)
{
if (!c->GetDesc())
return;
c->GetDesc()->Packet(m_buf, m_buf_len);
}
};
struct FEmpireChatPacket
{
packet_chat& p;
const char* orig_msg;
int orig_len;
char converted_msg[CHAT_MAX_LEN+1];
BYTE bEmpire;
int iMapIndex;
int namelen;
FEmpireChatPacket(packet_chat& p, const char* chat_msg, int len, BYTE bEmpire, int iMapIndex, int iNameLen)
: p(p), orig_msg(chat_msg), orig_len(len), bEmpire(bEmpire), iMapIndex(iMapIndex), namelen(iNameLen)
{
memset( converted_msg, 0, sizeof(converted_msg) );
}
void operator () (LPDESC d)
{
if (!d->GetCharacter())
return;
if (d->GetCharacter()->GetMapIndex() != iMapIndex)
return;
d->RawPacket(&p, sizeof(packet_chat));
if (d->GetEmpire() == bEmpire ||
bEmpire == 0 ||
d->GetCharacter()->GetGMLevel() > GM_PLAYER ||
d->GetCharacter()->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
{
d->Packet(orig_msg, orig_len);
}
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));
d->Packet(converted_msg, orig_len);
}
}
};
struct FYmirChatPacket
{
packet_chat& packet;
const char* m_szChat;
size_t m_lenChat;
const char* m_szName;
int m_iMapIndex;
BYTE m_bEmpire;
bool m_ring;
char m_orig_msg[CHAT_MAX_LEN+1];
int m_len_orig_msg;
char m_conv_msg[CHAT_MAX_LEN+1];
int m_len_conv_msg;
FYmirChatPacket(packet_chat& p, const char* chat, size_t len_chat, const char* name, size_t len_name, int iMapIndex, BYTE empire, bool ring)
: packet(p),
m_szChat(chat), m_lenChat(len_chat),
m_szName(name),
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; // ³Î ¹®ÀÚ Æ÷ÇÔ
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; // ³Î ¹®ÀÚ ¹ÌÆ÷ÇÔ
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Àº "??? : "ÀÇ ±æÀÌ
}
void operator() (LPDESC d)
{
if (!d->GetCharacter())
return;
if (d->GetCharacter()->GetMapIndex() != m_iMapIndex)
return;
if (m_ring ||
d->GetEmpire() == m_bEmpire ||
d->GetCharacter()->GetGMLevel() > GM_PLAYER ||
d->GetCharacter()->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
{
packet.size = m_len_orig_msg + sizeof(TPacketGCChat);
d->RawPacket(&packet, sizeof(packet_chat));
d->Packet(m_orig_msg, m_len_orig_msg);
}
else
{
packet.size = m_len_conv_msg + sizeof(TPacketGCChat);
d->RawPacket(&packet, sizeof(packet_chat));
d->Packet(m_conv_msg, m_len_conv_msg);
}
}
};
int CInputMain::Chat(LPCHARACTER ch, const char * data, size_t uiBytes)
{
const TPacketCGChat* pinfo = reinterpret_cast<const TPacketCGChat*>(data);
if (uiBytes < pinfo->size)
return -1;
const int iExtraLen = pinfo->size - sizeof(TPacketCGChat);
if (iExtraLen < 0)
{
SPDLOG_ERROR("invalid packet length (len {} size {} buffer {})", iExtraLen, pinfo->size, uiBytes);
ch->GetDesc()->SetPhase(PHASE_CLOSE);
return -1;
}
char buf[CHAT_MAX_LEN - (CHARACTER_NAME_MAX_LEN + 3) + 1];
strlcpy(buf, data + sizeof(TPacketCGChat), std::min<size_t>(iExtraLen + 1, sizeof(buf)));
const size_t buflen = strlen(buf);
if (buflen > 1 && *buf == '/')
{
interpret_command(ch, buf + 1, buflen - 1);
return iExtraLen;
}
if (ch->IncreaseChatCounter() >= 10)
{
if (ch->GetChatCounter() == 10)
{
SPDLOG_WARN("CHAT_HACK: {}", ch->GetName());
ch->GetDesc()->DelayedDisconnect(5);
}
return iExtraLen;
}
// äÆà ±ÝÁö Affect ó¸®
const CAffect* pAffect = ch->FindAffect(AFFECT_BLOCK_CHAT);
if (pAffect != NULL)
{
SendBlockChatInfo(ch, pAffect->lDuration);
return iExtraLen;
}
if (true == SpamBlockCheck(ch, buf, buflen))
{
return iExtraLen;
}
char chatbuf[CHAT_MAX_LEN + 1];
int len = snprintf(chatbuf, sizeof(chatbuf), "%s : %s", ch->GetName(), buf);
if (CHAT_TYPE_SHOUT == pinfo->type)
{
LogManager::instance().ShoutLog(g_bChannel, ch->GetEmpire(), chatbuf);
}
if (LC_IsCanada() == false)
{
CBanwordManager::instance().ConvertString(buf, buflen);
}
if (len < 0 || len >= (int) sizeof(chatbuf))
len = sizeof(chatbuf) - 1;
int processReturn = ProcessTextTag(ch, chatbuf, len);
if (0!=processReturn)
{
const TItemTable* pTable = ITEM_MANAGER::instance().GetTable(ITEM_PRISM);
if (NULL != pTable)
{
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);
}
return iExtraLen;
}
if (pinfo->type == CHAT_TYPE_SHOUT)
{
const int SHOUT_LIMIT_LEVEL = g_iUseLocale ? 15 : 3;
if (ch->GetLevel() < SHOUT_LIMIT_LEVEL)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xBF\xDC\xC4\xA1\xB1\xE2\xB4\xC2 \xB7\xB9\xBA\xA7 %d \xC0\xCC\xBB\xF3\xB8\xB8 \xBB\xE7\xBF\xEB \xB0\xA1\xB4\xC9 \xC7\xD5\xB4\xCF\xB4\xD9."), SHOUT_LIMIT_LEVEL);
return (iExtraLen);
}
if (thecore_heart->pulse - (int) ch->GetLastShoutPulse() < passes_per_sec * 15)
return (iExtraLen);
ch->SetLastShoutPulse(thecore_heart->pulse);
TPacketGGShout p;
p.bHeader = HEADER_GG_SHOUT;
p.bEmpire = ch->GetEmpire();
strlcpy(p.szText, chatbuf, sizeof(p.szText));
P2P_MANAGER::instance().Send(&p, sizeof(TPacketGGShout));
SendShout(chatbuf, ch->GetEmpire());
return (iExtraLen);
}
TPacketGCChat pack_chat;
pack_chat.header = HEADER_GC_CHAT;
pack_chat.size = sizeof(TPacketGCChat) + len;
pack_chat.type = pinfo->type;
pack_chat.id = ch->GetVID();
switch (pinfo->type)
{
case CHAT_TYPE_TALKING:
{
const DESC_MANAGER::DESC_SET & c_ref_set = DESC_MANAGER::instance().GetClientSet();
if (false)
{
std::for_each(c_ref_set.begin(), c_ref_set.end(),
FYmirChatPacket(pack_chat,
buf,
strlen(buf),
ch->GetName(),
strlen(ch->GetName()),
ch->GetMapIndex(),
ch->GetEmpire(),
ch->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE)));
}
else
{
std::for_each(c_ref_set.begin(), c_ref_set.end(),
FEmpireChatPacket(pack_chat,
chatbuf,
len,
(ch->GetGMLevel() > GM_PLAYER ||
ch->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE)) ? 0 : ch->GetEmpire(),
ch->GetMapIndex(), strlen(ch->GetName())));
}
}
break;
case CHAT_TYPE_PARTY:
{
if (!ch->GetParty())
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xC6\xC4\xC6\xBC \xC1\xDF\xC0\xCC \xBE\xC6\xB4\xD5\xB4\xCF\xB4\xD9."));
else
{
TEMP_BUFFER tbuf;
tbuf.write(&pack_chat, sizeof(pack_chat));
tbuf.write(chatbuf, len);
RawPacketToCharacterFunc f(tbuf.read_peek(), tbuf.size());
ch->GetParty()->ForEachOnlineMember(f);
}
}
break;
case CHAT_TYPE_GUILD:
{
if (!ch->GetGuild())
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB1\xE6\xB5\xE5\xBF\xA1 \xB0\xA1\xC0\xD4\xC7\xCF\xC1\xF6 \xBE\xCA\xBE\xD2\xBD\xC0\xB4\xCF\xB4\xD9."));
else
ch->GetGuild()->Chat(chatbuf);
}
break;
default:
SPDLOG_ERROR("Unknown chat type {}", pinfo->type);
break;
}
return (iExtraLen);
}
void CInputMain::ItemUse(LPCHARACTER ch, const char * data)
{
ch->UseItem(((struct command_item_use *) data)->Cell);
}
void CInputMain::ItemToItem(LPCHARACTER ch, const char * pcData)
{
TPacketCGItemUseToItem * p = (TPacketCGItemUseToItem *) pcData;
if (ch)
ch->UseItem(p->Cell, p->TargetCell);
}
void CInputMain::ItemDrop(LPCHARACTER ch, const char * data)
{
struct command_item_drop * pinfo = (struct command_item_drop *) data;
//MONARCH_LIMIT
//if (ch->IsMonarch())
// return;
//END_MONARCH_LIMIT
if (!ch)
return;
// ¿¤Å©°¡ 0º¸´Ù Å©¸é ¿¤Å©¸¦ ¹ö¸®´Â °Í ÀÌ´Ù.
if (pinfo->gold > 0)
ch->DropGold(pinfo->gold);
else
ch->DropItem(pinfo->Cell);
}
void CInputMain::ItemDrop2(LPCHARACTER ch, const char * data)
{
//MONARCH_LIMIT
//if (ch->IsMonarch())
// return;
//END_MONARCH_LIMIT
TPacketCGItemDrop2 * pinfo = (TPacketCGItemDrop2 *) data;
// ¿¤Å©°¡ 0º¸´Ù Å©¸é ¿¤Å©¸¦ ¹ö¸®´Â °Í ÀÌ´Ù.
if (!ch)
return;
if (pinfo->gold > 0)
ch->DropGold(pinfo->gold);
else
ch->DropItem(pinfo->Cell, pinfo->count);
}
void CInputMain::ItemMove(LPCHARACTER ch, const char * data)
{
struct command_item_move * pinfo = (struct command_item_move *) data;
if (ch)
ch->MoveItem(pinfo->Cell, pinfo->CellTo, pinfo->count);
}
void CInputMain::ItemPickup(LPCHARACTER ch, const char * data)
{
struct command_item_pickup * pinfo = (struct command_item_pickup*) data;
if (ch)
ch->PickupItem(pinfo->vid);
}
void CInputMain::QuickslotAdd(LPCHARACTER ch, const char * data)
{
struct command_quickslot_add * pinfo = (struct command_quickslot_add *) data;
ch->SetQuickslot(pinfo->pos, pinfo->slot);
}
void CInputMain::QuickslotDelete(LPCHARACTER ch, const char * data)
{
struct command_quickslot_del * pinfo = (struct command_quickslot_del *) data;
ch->DelQuickslot(pinfo->pos);
}
void CInputMain::QuickslotSwap(LPCHARACTER ch, const char * data)
{
struct command_quickslot_swap * pinfo = (struct command_quickslot_swap *) data;
ch->SwapQuickslot(pinfo->pos, pinfo->change_pos);
}
int CInputMain::Messenger(LPCHARACTER ch, const char* c_pData, size_t uiBytes)
{
TPacketCGMessenger* p = (TPacketCGMessenger*) c_pData;
if (uiBytes < sizeof(TPacketCGMessenger))
return -1;
c_pData += sizeof(TPacketCGMessenger);
uiBytes -= sizeof(TPacketCGMessenger);
switch (p->subheader)
{
case MESSENGER_SUBHEADER_CG_ADD_BY_VID:
{
if (uiBytes < sizeof(TPacketCGMessengerAddByVID))
return -1;
TPacketCGMessengerAddByVID * p2 = (TPacketCGMessengerAddByVID *) c_pData;
LPCHARACTER ch_companion = CHARACTER_MANAGER::instance().Find(p2->vid);
if (!ch_companion)
return sizeof(TPacketCGMessengerAddByVID);
if (ch->IsObserverMode())
return sizeof(TPacketCGMessengerAddByVID);
if (ch_companion->IsBlockMode(BLOCK_MESSENGER_INVITE))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xBB\xF3\xB4\xEB\xB9\xE6\xC0\xCC \xB8\xDE\xBD\xC5\xC1\xAE \xC3\xDF\xB0\xA1 \xB0\xC5\xBA\xCE \xBB\xF3\xC5\xC2\xC0\xD4\xB4\xCF\xB4\xD9."));
return sizeof(TPacketCGMessengerAddByVID);
}
LPDESC d = ch_companion->GetDesc();
if (!d)
return sizeof(TPacketCGMessengerAddByVID);
if (ch->GetGMLevel() == GM_PLAYER && ch_companion->GetGMLevel() != GM_PLAYER)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB8\xDE\xBD\xC5\xC1\xAE> \xBF\xEE\xBF\xB5\xC0\xDA\xB4\xC2 \xB8\xDE\xBD\xC5\xC1\xAE\xBF\xA1 \xC3\xDF\xB0\xA1\xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return sizeof(TPacketCGMessengerAddByVID);
}
if (ch->GetDesc() == d) // ÀÚ½ÅÀº Ãß°¡ÇÒ ¼ö ¾ø´Ù.
return sizeof(TPacketCGMessengerAddByVID);
MessengerManager::instance().RequestToAdd(ch, ch_companion);
//MessengerManager::instance().AddToList(ch->GetName(), ch_companion->GetName());
}
return sizeof(TPacketCGMessengerAddByVID);
case MESSENGER_SUBHEADER_CG_ADD_BY_NAME:
{
if (uiBytes < CHARACTER_NAME_MAX_LEN)
return -1;
char name[CHARACTER_NAME_MAX_LEN + 1];
strlcpy(name, c_pData, sizeof(name));
if (ch->GetGMLevel() == GM_PLAYER && gm_get_level(name) != GM_PLAYER)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB8\xDE\xBD\xC5\xC1\xAE> \xBF\xEE\xBF\xB5\xC0\xDA\xB4\xC2 \xB8\xDE\xBD\xC5\xC1\xAE\xBF\xA1 \xC3\xDF\xB0\xA1\xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return CHARACTER_NAME_MAX_LEN;
}
LPCHARACTER tch = CHARACTER_MANAGER::instance().FindPC(name);
if (!tch)
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) // ÀÚ½ÅÀº Ãß°¡ÇÒ ¼ö ¾ø´Ù.
return CHARACTER_NAME_MAX_LEN;
if (tch->IsBlockMode(BLOCK_MESSENGER_INVITE) == true)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xBB\xF3\xB4\xEB\xB9\xE6\xC0\xCC \xB8\xDE\xBD\xC5\xC1\xAE \xC3\xDF\xB0\xA1 \xB0\xC5\xBA\xCE \xBB\xF3\xC5\xC2\xC0\xD4\xB4\xCF\xB4\xD9."));
}
else
{
// ¸Þ½ÅÀú°¡ ij¸¯ÅÍ´ÜÀ§°¡ µÇ¸é¼­ º¯°æ
MessengerManager::instance().RequestToAdd(ch, tch);
//MessengerManager::instance().AddToList(ch->GetName(), tch->GetName());
}
}
}
return CHARACTER_NAME_MAX_LEN;
case MESSENGER_SUBHEADER_CG_REMOVE:
{
if (uiBytes < CHARACTER_NAME_MAX_LEN)
return -1;
char char_name[CHARACTER_NAME_MAX_LEN + 1];
strlcpy(char_name, c_pData, sizeof(char_name));
MessengerManager::instance().RemoveFromList(ch->GetName(), char_name);
}
return CHARACTER_NAME_MAX_LEN;
default:
SPDLOG_ERROR("CInputMain::Messenger : Unknown subheader {} : {}", p->subheader, ch->GetName());
break;
}
return 0;
}
int CInputMain::Shop(LPCHARACTER ch, const char * data, size_t uiBytes)
{
TPacketCGShop * p = (TPacketCGShop *) data;
if (uiBytes < sizeof(TPacketCGShop))
return -1;
SPDLOG_TRACE("CInputMain::Shop() ==> SubHeader {}", p->subheader);
const char * c_pData = data + sizeof(TPacketCGShop);
uiBytes -= sizeof(TPacketCGShop);
switch (p->subheader)
{
case SHOP_SUBHEADER_CG_END:
SPDLOG_DEBUG("INPUT: {} SHOP: END", ch->GetName());
CShopManager::instance().StopShopping(ch);
return 0;
case SHOP_SUBHEADER_CG_BUY:
{
if (uiBytes < sizeof(BYTE) + sizeof(BYTE))
return -1;
BYTE bPos = *(c_pData + 1);
SPDLOG_DEBUG("INPUT: {} SHOP: BUY {}", ch->GetName(), bPos);
CShopManager::instance().Buy(ch, bPos);
return (sizeof(BYTE) + sizeof(BYTE));
}
case SHOP_SUBHEADER_CG_SELL:
{
if (uiBytes < sizeof(BYTE))
return -1;
BYTE pos = *c_pData;
SPDLOG_DEBUG("INPUT: {} SHOP: SELL", ch->GetName());
CShopManager::instance().Sell(ch, pos);
return sizeof(BYTE);
}
case SHOP_SUBHEADER_CG_SELL2:
{
if (uiBytes < sizeof(BYTE) + sizeof(BYTE))
return -1;
BYTE pos = *(c_pData++);
BYTE count = *(c_pData);
SPDLOG_DEBUG("INPUT: {} SHOP: SELL2", ch->GetName());
CShopManager::instance().Sell(ch, pos, count);
return sizeof(BYTE) + sizeof(BYTE);
}
default:
SPDLOG_ERROR("CInputMain::Shop : Unknown subheader {} : {}", p->subheader, ch->GetName());
break;
}
return 0;
}
void CInputMain::OnClick(LPCHARACTER ch, const char * data)
{
struct command_on_click * pinfo = (struct command_on_click *) data;
LPCHARACTER victim;
if ((victim = CHARACTER_MANAGER::instance().Find(pinfo->vid)))
victim->OnClick(ch);
else
SPDLOG_TRACE("CInputMain::OnClick {}.Click.NOT_EXIST_VID[{}]", ch->GetName(), pinfo->vid);
}
void CInputMain::Exchange(LPCHARACTER ch, const char * data)
{
struct command_exchange * pinfo = (struct command_exchange *) data;
LPCHARACTER to_ch = NULL;
if (!ch->CanHandleItem())
return;
int iPulse = thecore_pulse();
if ((to_ch = CHARACTER_MANAGER::instance().Find(pinfo->arg1)))
{
if (iPulse - to_ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
{
to_ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB0\xC5\xB7\xA1 \xC8\xC4 %d\xC3\xCA \xC0\xCC\xB3\xBB\xBF\xA1 \xC3\xA2\xB0\xED\xB8\xA6 \xBF\xAD\xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."), g_nPortalLimitTime);
return;
}
if( true == to_ch->IsDead() )
{
return;
}
}
SPDLOG_DEBUG("CInputMain()::Exchange() SubHeader {} ", pinfo->sub_header);
if (iPulse - ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB0\xC5\xB7\xA1 \xC8\xC4 %d\xC3\xCA \xC0\xCC\xB3\xBB\xBF\xA1 \xC3\xA2\xB0\xED\xB8\xA6 \xBF\xAD\xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."), g_nPortalLimitTime);
return;
}
switch (pinfo->sub_header)
{
case EXCHANGE_SUBHEADER_CG_START: // arg1 == vid of target character
if (!ch->GetExchange())
{
if ((to_ch = CHARACTER_MANAGER::instance().Find(pinfo->arg1)))
{
//MONARCH_LIMIT
/*
if (to_ch->IsMonarch() || ch->IsMonarch())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB1\xBA\xC1\xD6\xBF\xCD\xB4\xC2 \xB0\xC5\xB7\xA1\xB8\xA6 \xC7\xD2\xBC\xF6\xB0\xA1 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9"), g_nPortalLimitTime);
return;
}
//END_MONARCH_LIMIT
*/
if (iPulse - ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xC3\xA2\xB0\xED\xB8\xA6 \xBF\xAC\xC8\xC4 %d\xC3\xCA \xC0\xCC\xB3\xBB\xBF\xA1\xB4\xC2 \xB0\xC5\xB7\xA1\xB8\xA6 \xC7\xD2\xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."), g_nPortalLimitTime);
if (test_server)
ch->ChatPacket(CHAT_TYPE_INFO, "[TestOnly][Safebox]Pulse %d LoadTime %d PASS %d", iPulse, ch->GetSafeboxLoadTime(), PASSES_PER_SEC(g_nPortalLimitTime));
return;
}
if (iPulse - to_ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
{
to_ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xC3\xA2\xB0\xED\xB8\xA6 \xBF\xAC\xC8\xC4 %d\xC3\xCA \xC0\xCC\xB3\xBB\xBF\xA1\xB4\xC2 \xB0\xC5\xB7\xA1\xB8\xA6 \xC7\xD2\xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."), g_nPortalLimitTime);
if (test_server)
to_ch->ChatPacket(CHAT_TYPE_INFO, "[TestOnly][Safebox]Pulse %d LoadTime %d PASS %d", iPulse, to_ch->GetSafeboxLoadTime(), PASSES_PER_SEC(g_nPortalLimitTime));
return;
}
if (ch->GetGold() >= GOLD_MAX)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xBE\xD7\xBC\xF6\xB0\xA1 20\xBE\xEF \xB3\xC9\xC0\xBB \xC3\xCA\xB0\xFA\xC7\xCF\xBF\xA9 \xB0\xC5\xB7\xA1\xB8\xA6 \xC7\xD2\xBC\xF6\xB0\xA1 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9.."));
SPDLOG_ERROR("[OVERFLOG_GOLD] START ({}) id {} name {} ", ch->GetGold(), ch->GetPlayerID(), ch->GetName());
return;
}
if (to_ch->IsPC())
{
if (quest::CQuestManager::instance().GiveItemToPC(ch->GetPlayerID(), to_ch))
{
SPDLOG_DEBUG("Exchange canceled by quest {} {}", ch->GetName(), to_ch->GetName());
return;
}
}
if (ch->GetMyShop() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->IsCubeOpen())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB4\xD9\xB8\xA5 \xB0\xC5\xB7\xA1\xC1\xDF\xC0\xCF\xB0\xE6\xBF\xEC \xB0\xB3\xC0\xCE\xBB\xF3\xC1\xA1\xC0\xBB \xBF\xAD\xBC\xF6\xB0\xA1 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return;
}
ch->ExchangeStart(to_ch);
}
}
break;
case EXCHANGE_SUBHEADER_CG_ITEM_ADD: // arg1 == position of item, arg2 == position in exchange window
if (ch->GetExchange())
{
if (ch->GetExchange()->GetCompany()->GetAcceptStatus() != true)
ch->GetExchange()->AddItem(pinfo->Pos, pinfo->arg2);
}
break;
case EXCHANGE_SUBHEADER_CG_ITEM_DEL: // arg1 == position of item
if (ch->GetExchange())
{
if (ch->GetExchange()->GetCompany()->GetAcceptStatus() != true)
ch->GetExchange()->RemoveItem(pinfo->arg1);
}
break;
case EXCHANGE_SUBHEADER_CG_ELK_ADD: // arg1 == amount of gold
if (ch->GetExchange())
{
const int64_t nTotalGold = static_cast<int64_t>(ch->GetExchange()->GetCompany()->GetOwner()->GetGold()) + static_cast<int64_t>(pinfo->arg1);
if (GOLD_MAX <= nTotalGold)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xBB\xF3\xB4\xEB\xB9\xE6\xC0\xC7 \xC3\xD1\xB1\xDD\xBE\xD7\xC0\xCC 20\xBE\xEF \xB3\xC9\xC0\xBB \xC3\xCA\xB0\xFA\xC7\xCF\xBF\xA9 \xB0\xC5\xB7\xA1\xB8\xA6 \xC7\xD2\xBC\xF6\xB0\xA1 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9.."));
SPDLOG_ERROR("[OVERFLOW_GOLD] ELK_ADD ({}) id {} name {} ",
ch->GetExchange()->GetCompany()->GetOwner()->GetGold(),
ch->GetExchange()->GetCompany()->GetOwner()->GetPlayerID(),
ch->GetExchange()->GetCompany()->GetOwner()->GetName());
return;
}
if (ch->GetExchange()->GetCompany()->GetAcceptStatus() != true)
ch->GetExchange()->AddGold(pinfo->arg1);
}
break;
case EXCHANGE_SUBHEADER_CG_ACCEPT: // arg1 == not used
if (ch->GetExchange())
{
SPDLOG_DEBUG("CInputMain()::Exchange() ==> ACCEPT ");
ch->GetExchange()->Accept(true);
}
break;
case EXCHANGE_SUBHEADER_CG_CANCEL: // arg1 == not used
if (ch->GetExchange())
ch->GetExchange()->Cancel();
break;
}
}
void CInputMain::Position(LPCHARACTER ch, const char * data)
{
struct command_position * pinfo = (struct command_position *) data;
switch (pinfo->position)
{
case POSITION_GENERAL:
ch->Standup();
break;
case POSITION_SITTING_CHAIR:
ch->Sitdown(0);
break;
case POSITION_SITTING_GROUND:
ch->Sitdown(1);
break;
}
}
static const int ComboSequenceBySkillLevel[3][8] =
{
// 0 1 2 3 4 5 6 7
{ 14, 15, 16, 17, 0, 0, 0, 0 },
{ 14, 15, 16, 18, 20, 0, 0, 0 },
{ 14, 15, 16, 18, 19, 17, 0, 0 },
};
#define COMBO_HACK_ALLOWABLE_MS 100
// [2013 09 11 CYH]
DWORD ClacValidComboInterval( LPCHARACTER ch, BYTE bArg )
{
int nInterval = 300;
float fAdjustNum = 1.5f; // ÀÏ¹Ý À¯Àú°¡ speed hack ¿¡ °É¸®´Â °ÍÀ» ¸·±â À§ÇØ. 2013.09.10 CYH
if( !ch )
{
SPDLOG_ERROR("ClacValidComboInterval() ch is NULL");
return nInterval;
}
if( bArg == 13 )
{
float normalAttackDuration = CMotionManager::instance().GetNormalAttackDuration(ch->GetRaceNum());
nInterval = (int) (normalAttackDuration / (((float) ch->GetPoint(POINT_ATT_SPEED) / 100.f) * 900.f) + fAdjustNum );
}
else if( bArg == 14 )
{
nInterval = (int)(ani_combo_speed(ch, 1 ) / ((ch->GetPoint(POINT_ATT_SPEED) / 100.f) + fAdjustNum) );
}
else if( bArg > 14 && bArg << 22 )
{
nInterval = (int)(ani_combo_speed(ch, bArg - 13 ) / ((ch->GetPoint(POINT_ATT_SPEED) / 100.f) + fAdjustNum) );
}
else
{
SPDLOG_ERROR("ClacValidComboInterval() Invalid bArg({}) ch({})", bArg, ch->GetName() );
}
return nInterval;
}
bool CheckComboHack(LPCHARACTER ch, BYTE bArg, DWORD dwTime, bool CheckSpeedHack)
{
// Áװųª ±âÀý »óÅ¿¡¼­´Â °ø°ÝÇÒ ¼ö ¾øÀ¸¹Ç·Î, skipÇÑ´Ù.
// ÀÌ·¸°Ô ÇÏÁö ¸»°í, CHRACTER::CanMove()¿¡
// if (IsStun() || IsDead()) return false;
// ¸¦ Ãß°¡ÇÏ´Â°Ô ¸Â´Ù°í »ý°¢Çϳª,
// ÀÌ¹Ì ´Ù¸¥ ºÎºÐ¿¡¼­ CanMove()´Â IsStun(), IsDead()°ú
// µ¶¸³ÀûÀ¸·Î üũÇÏ°í Àֱ⠶§¹®¿¡ ¼öÁ¤¿¡ ÀÇÇÑ ¿µÇâÀ»
// ÃÖ¼ÒÈ­Çϱâ À§ÇØ ÀÌ·¸°Ô ¶«»§ Äڵ带 ½á³õ´Â´Ù.
if (ch->IsStun() || ch->IsDead())
return false;
int ComboInterval = dwTime - ch->GetLastComboTime();
int HackScalar = 0; // ±âº» ½ºÄ®¶ó ´ÜÀ§ 1
// [2013 09 11 CYH] debugging log
/*SPDLOG_DEBUG("COMBO_TEST_LOG: {} arg:{} interval:{} valid:{} atkspd:{} riding:{}",
ch->GetName(),
bArg,
ComboInterval,
ch->GetValidComboInterval(),
ch->GetPoint(POINT_ATT_SPEED),
ch->IsRiding() ? "yes" : "no");*/
#if 0
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. Â÷·Ê´ë·Î Áõ°¡ÇÑ´Ù.
if (bArg == 14)
{
if (CheckSpeedHack && ComboInterval > 0 && ComboInterval < ch->GetValidComboInterval() - COMBO_HACK_ALLOWABLE_MS)
{
// FIXME ù¹ø° ÄÞº¸´Â ÀÌ»óÇÏ°Ô »¡¸® ¿Ã ¼ö°¡ À־ 300À¸·Î ³ª´® -_-;
// ´Ù¼öÀÇ ¸ó½ºÅÍ¿¡ ÀÇÇØ ´Ù¿îµÇ´Â »óȲ¿¡¼­ °ø°ÝÀ» Çϸé
// ù¹ø° ÄÞº¸°¡ ¸Å¿ì ÀûÀº ÀÎÅ͹ú·Î µé¾î¿À´Â »óȲ ¹ß»ý.
// ÀÌ·Î ÀÎÇØ ÄÞº¸ÇÙÀ¸·Î ƨ±â´Â °æ¿ì°¡ ÀÖ¾î ´ÙÀ½ ÄÚµå ºñ È°¼ºÈ­.
//HackScalar = 1 + (ch->GetValidComboInterval() - ComboInterval) / 300;
//SPDLOG_WARN("COMBO_HACK: 2 {} arg:{} interval:{} valid:{} atkspd:{} riding:{}",
// ch->GetName(),
// bArg,
// ComboInterval,
// ch->GetValidComboInterval(),
// ch->GetPoint(POINT_ATT_SPEED),
// ch->IsRiding() ? "yes" : "no");
}
ch->SetComboSequence(1);
// 2013 09 11 CYH edited
//ch->SetValidComboInterval((int) (ani_combo_speed(ch, 1) / (ch->GetPoint(POINT_ATT_SPEED) / 100.f)));
ch->SetValidComboInterval( ClacValidComboInterval(ch, bArg) );
ch->SetLastComboTime(dwTime);
}
else if (bArg > 14 && bArg < 22)
{
int idx = std::min<int>(2, ch->GetComboIndex());
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 &&
ch->GetJob() == JOB_ASSASSIN &&
ch->GetWear(WEAR_WEAPON) &&
ch->GetWear(WEAR_WEAPON)->GetSubType() == WEAPON_DAGGER)
ch->SetValidComboInterval(300);
else if (ComboSequenceBySkillLevel[idx][ch->GetComboSequence()] != bArg)
{
HackScalar = 1;
ch->SetValidComboInterval(300);
SPDLOG_WARN("COMBO_HACK: 3 {} arg:{} valid:{} combo_idx:{} combo_seq:{}",
ch->GetName(),
bArg,
ComboSequenceBySkillLevel[idx][ch->GetComboSequence()],
idx,
ch->GetComboSequence());
}
else
{
if (CheckSpeedHack && ComboInterval < ch->GetValidComboInterval() - COMBO_HACK_ALLOWABLE_MS)
{
HackScalar = 1 + (ch->GetValidComboInterval() - ComboInterval) / 100;
SPDLOG_WARN("COMBO_HACK: 2 {} arg:{} interval:{} valid:{} atkspd:{} riding:{}",
ch->GetName(),
bArg,
ComboInterval,
ch->GetValidComboInterval(),
ch->GetPoint(POINT_ATT_SPEED),
ch->IsRiding() ? "yes" : "no");
}
// ¸»À» ÅÀÀ» ¶§´Â 15¹ø ~ 16¹øÀ» ¹Ýº¹ÇÑ´Ù
//if (ch->IsHorseRiding())
if (ch->IsRiding())
ch->SetComboSequence(ch->GetComboSequence() == 1 ? 2 : 1);
else
ch->SetComboSequence(ch->GetComboSequence() + 1);
// 2013 09 11 CYH edited
//ch->SetValidComboInterval((int) (ani_combo_speed(ch, bArg - 13) / (ch->GetPoint(POINT_ATT_SPEED) / 100.f)));
ch->SetValidComboInterval( ClacValidComboInterval(ch, bArg) );
ch->SetLastComboTime(dwTime);
}
}
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:{}",
// ch->GetName(),
// bArg,
// ComboInterval,
// ch->GetValidComboInterval(),
// ch->GetPoint(POINT_ATT_SPEED));
}
if (ch->GetRaceNum() >= MAIN_RACE_MAX_NUM)
{
// POLYMORPH_BUG_FIX
// DELETEME
/*
const CMotion * pkMotion = CMotionManager::instance().GetMotion(ch->GetRaceNum(), MAKE_MOTION_KEY(MOTION_MODE_GENERAL, MOTION_NORMAL_ATTACK));
if (!pkMotion)
SPDLOG_ERROR("cannot find motion by race {}", ch->GetRaceNum());
else
{
// Á¤»óÀû °è»êÀ̶ó¸é 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);
}
*/
// 2013 09 11 CYH edited
//float normalAttackDuration = CMotionManager::instance().GetNormalAttackDuration(ch->GetRaceNum());
//int k = (int) (normalAttackDuration / ((float) ch->GetPoint(POINT_ATT_SPEED) / 100.f) * 900.f);
//ch->SetValidComboInterval(k);
ch->SetValidComboInterval( ClacValidComboInterval(ch, bArg) );
ch->SetLastComboTime(dwTime);
// END_OF_POLYMORPH_BUG_FIX
}
else
{
// ¸»ÀÌ ¾ÈµÇ´Â ÄÞº¸°¡ ¿Ô´Ù ÇØÄ¿ÀÏ °¡´É¼º?
//if (ch->GetDesc()->DelayedDisconnect(Random::get(2, 9)))
//{
// LogManager::instance().HackLog("Hacker", ch);
// SPDLOG_WARN("HACKER: {} arg {}", ch->GetName(), bArg);
//}
// À§ ÄÚµå·Î ÀÎÇØ, Æú¸®¸ðÇÁ¸¦ Ǫ´Â Áß¿¡ °ø°Ý Çϸé,
// °¡²û ÇÙÀ¸·Î ÀνÄÇÏ´Â °æ¿ì°¡ ÀÖ´Ù.
// ÀÚ¼¼È÷ ¸»Çô¸é,
// ¼­¹ö¿¡¼­ poly 0¸¦ ó¸®ÇßÁö¸¸,
// Ŭ¶ó¿¡¼­ ±× ÆÐŶÀ» ¹Þ±â Àü¿¡, ¸÷À» °ø°Ý. <- Áï, ¸÷ÀÎ »óÅ¿¡¼­ °ø°Ý.
//
// ±×·¯¸é Ŭ¶ó¿¡¼­´Â ¼­¹ö¿¡ ¸÷ »óÅ·Π°ø°ÝÇß´Ù´Â Ä¿¸Çµå¸¦ º¸³»°í (arg == 13)
//
// ¼­¹ö¿¡¼­´Â race´Â Àΰ£Àε¥ °ø°ÝÇüÅ´ ¸÷ÀÎ ³ðÀÌ´Ù! ¶ó°í ÇÏ¿© ÇÙüũ¸¦ Çß´Ù.
// »ç½Ç °ø°Ý ÆÐÅÏ¿¡ ´ëÇÑ °ÍÀº Ŭ¶óÀ̾ðÆ®¿¡¼­ ÆÇ´ÜÇؼ­ º¸³¾ °ÍÀÌ ¾Æ´Ï¶ó,
// ¼­¹ö¿¡¼­ ÆÇ´ÜÇØ¾ß ÇÒ °ÍÀε¥... ¿Ö ÀÌ·¸°Ô ÇسùÀ»±î...
// by rtsummit
}
}
else
{
// ¸»ÀÌ ¾ÈµÇ´Â ÄÞº¸°¡ ¿Ô´Ù ÇØÄ¿ÀÏ °¡´É¼º?
if (ch->GetDesc()->DelayedDisconnect(Random::get(2, 9)))
{
LogManager::instance().HackLog("Hacker", ch);
SPDLOG_WARN("HACKER: {} arg {}", ch->GetName(), bArg);
}
HackScalar = 10;
ch->SetValidComboInterval(300);
}
if (HackScalar)
{
// ¸»¿¡ Ÿ°Å³ª ³»·ÈÀ» ¶§ 1.5ÃÊ°£ °ø°ÝÀº ÇÙÀ¸·Î °£ÁÖÇÏÁö ¾ÊµÇ °ø°Ý·ÂÀº ¾ø°Ô Çϴ ó¸®
if (get_dword_time() - ch->GetLastMountTime() > 1500)
ch->IncreaseComboHackCount(1 + HackScalar);
ch->SkipComboAttackByTime(ch->GetValidComboInterval());
}
return HackScalar;
}
void CInputMain::Move(LPCHARACTER ch, const char * data)
{
if (!ch->CanMove())
return;
struct command_move * pinfo = (struct command_move *) data;
if (pinfo->bFunc >= FUNC_MAX_NUM && !(pinfo->bFunc & 0x80))
{
SPDLOG_ERROR("invalid move type: {}", ch->GetName());
return;
}
//enum EMoveFuncType
//{
// FUNC_WAIT,
// FUNC_MOVE,
// FUNC_ATTACK,
// FUNC_COMBO,
// FUNC_MOB_SKILL,
// _FUNC_SKILL,
// FUNC_MAX_NUM,
// FUNC_SKILL = 0x80,
//};
// ÅÚ·¹Æ÷Æ® Ç٠üũ
// if (!test_server) //2012.05.15 ±è¿ë¿í : Å×¼·¿¡¼­ (¹«Àû»óÅ·Î) ´Ù¼ö ¸ó½ºÅÍ »ó´ë·Î ´Ù¿îµÇ¸é¼­ °ø°Ý½Ã ÄÞº¸ÇÙÀ¸·Î Á×´Â ¹®Á¦°¡ ÀÖ¾ú´Ù.
{
const float fDist = DISTANCE_SQRT((ch->GetX() - pinfo->lX) / 100, (ch->GetY() - pinfo->lY) / 100);
if (((false == ch->IsRiding() && fDist > 25) || fDist > 40) && OXEVENT_MAP_INDEX != ch->GetMapIndex())
{
if( false == LC_IsEurope() )
{
const PIXEL_POSITION & warpPos = ch->GetWarpPosition();
if (warpPos.x == 0 && warpPos.y == 0)
LogManager::instance().HackLog("Teleport", ch); // ºÎÁ¤È®ÇÒ ¼ö ÀÖÀ½
}
SPDLOG_WARN("MOVE: {} trying to move too far (dist: {:.1f}m) Riding({})", ch->GetName(), fDist, ch->IsRiding());
ch->Show(ch->GetMapIndex(), ch->GetX(), ch->GetY(), ch->GetZ());
ch->Stop();
return;
}
//
// ½ºÇǵåÇÙ(SPEEDHACK) Check
//
DWORD dwCurTime = get_dword_time();
// ½Ã°£À» SyncÇÏ°í 7ÃÊ ÈÄ ºÎÅÍ °Ë»çÇÑ´Ù. (20090702 ÀÌÀü¿£ 5ÃÊ¿´À½)
bool CheckSpeedHack = (false == ch->GetDesc()->IsHandshaking() && dwCurTime - ch->GetDesc()->GetClientTime() > 7000);
if (CheckSpeedHack)
{
int iDelta = (int) (pinfo->dwTime - ch->GetDesc()->GetClientTime());
int iServerDelta = (int) (dwCurTime - ch->GetDesc()->GetClientTime());
iDelta = (int) (dwCurTime - pinfo->dwTime);
// ½Ã°£ÀÌ ´Ê°Ô°£´Ù. ÀÏ´Ü ·Î±×¸¸ ÇصдÙ. ÁøÂ¥ ÀÌ·± »ç¶÷µéÀÌ ¸¹ÀºÁö üũÇؾßÇÔ. TODO
if (iDelta >= 30000)
{
SPDLOG_WARN("SPEEDHACK: slow timer name {} delta {}", ch->GetName(), iDelta);
ch->GetDesc()->DelayedDisconnect(3);
}
// 1ÃÊ¿¡ 20msec »¡¸® °¡´Â°Å ±îÁö´Â ÀÌÇØÇÑ´Ù.
else if (iDelta < -(iServerDelta / 50))
{
SPDLOG_WARN("SPEEDHACK: DETECTED! {} (delta {} {})", ch->GetName(), iDelta, iServerDelta);
ch->GetDesc()->DelayedDisconnect(3);
}
}
//
// ÄÞº¸ÇÙ ¹× ½ºÇǵåÇ٠üũ
//
if (pinfo->bFunc == FUNC_COMBO && g_bCheckMultiHack)
{
CheckComboHack(ch, pinfo->bArg, pinfo->dwTime, CheckSpeedHack); // ÄÞº¸ üũ
}
}
if (pinfo->bFunc == FUNC_MOVE)
{
if (ch->GetLimitPoint(POINT_MOV_SPEED) == 0)
return;
ch->SetRotation(pinfo->bRot * 5); // Áߺ¹ ÄÚµå
ch->ResetStopTime(); // ""
ch->Goto(pinfo->lX, pinfo->lY);
}
else
{
if (pinfo->bFunc == FUNC_ATTACK || pinfo->bFunc == FUNC_COMBO)
ch->OnMove(true);
else if (pinfo->bFunc & FUNC_SKILL)
{
const int MASK_SKILL_MOTION = 0x7F;
unsigned int motion = pinfo->bFunc & MASK_SKILL_MOTION;
if (!ch->IsUsableSkillMotion(motion))
{
const char* name = ch->GetName();
unsigned int job = ch->GetJob();
unsigned int group = ch->GetSkillGroup();
char szBuf[256];
snprintf(szBuf, sizeof(szBuf), "SKILL_HACK: name=%s, job=%d, group=%d, motion=%d", name, job, group, motion);
LogManager::instance().HackLog(szBuf, ch->GetDesc()->GetAccountTable().login, ch->GetName(), ch->GetDesc()->GetHostName());
SPDLOG_WARN("{}", szBuf);
if (test_server)
{
ch->GetDesc()->DelayedDisconnect(Random::get(2, 8));
ch->ChatPacket(CHAT_TYPE_INFO, szBuf);
}
else
{
ch->GetDesc()->DelayedDisconnect(Random::get(150, 500));
}
}
ch->OnMove();
}
ch->SetRotation(pinfo->bRot * 5); // Áߺ¹ ÄÚµå
ch->ResetStopTime(); // ""
ch->Move(pinfo->lX, pinfo->lY);
ch->Stop();
ch->StopStaminaConsume();
}
TPacketGCMove pack;
pack.bHeader = HEADER_GC_MOVE;
pack.bFunc = pinfo->bFunc;
pack.bArg = pinfo->bArg;
pack.bRot = pinfo->bRot;
pack.dwVID = ch->GetVID();
pack.lX = pinfo->lX;
pack.lY = pinfo->lY;
pack.dwTime = pinfo->dwTime;
pack.dwDuration = (pinfo->bFunc == FUNC_MOVE) ? ch->GetCurrentMoveDuration() : 0;
ch->PacketAround(&pack, sizeof(TPacketGCMove), ch);
/*
if (pinfo->dwTime == 10653691) // µð¹ö°Å ¹ß°ß
{
if (ch->GetDesc()->DelayedDisconnect(Random::get(15, 30)))
LogManager::instance().HackLog("Debugger", ch);
}
else if (pinfo->dwTime == 10653971) // Softice ¹ß°ß
{
if (ch->GetDesc()->DelayedDisconnect(Random::get(15, 30)))
LogManager::instance().HackLog("Softice", ch);
}
*/
/*
SPDLOG_TRACE(
"MOVE: {} Func:{} Arg:{} Pos:{}x{} Time:{} Dist:{:.1f}",
ch->GetName(),
pinfo->bFunc,
pinfo->bArg,
pinfo->lX / 100,
pinfo->lY / 100,
pinfo->dwTime,
fDist);
*/
}
void CInputMain::Attack(LPCHARACTER ch, const BYTE header, const char* data)
{
if (NULL == ch)
return;
struct type_identifier
{
BYTE header;
BYTE type;
};
const struct type_identifier* const type = reinterpret_cast<const struct type_identifier*>(data);
if (type->type > 0)
{
if (false == ch->CanUseSkill(type->type))
{
return;
}
switch (type->type)
{
case SKILL_GEOMPUNG:
case SKILL_SANGONG:
case SKILL_YEONSA:
case SKILL_KWANKYEOK:
case SKILL_HWAJO:
case SKILL_GIGUNG:
case SKILL_PABEOB:
case SKILL_MARYUNG:
case SKILL_TUSOK:
case SKILL_MAHWAN:
case SKILL_BIPABU:
case SKILL_NOEJEON:
case SKILL_CHAIN:
case SKILL_HORSE_WILDATTACK_RANGE:
if (HEADER_CG_SHOOT != type->header)
{
if (test_server)
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Attack :name[%s] Vnum[%d] can't use skill by attack(warning)"), type->type);
return;
}
break;
}
}
switch (header)
{
case HEADER_CG_ATTACK:
{
if (NULL == ch->GetDesc())
return;
const TPacketCGAttack* const packMelee = reinterpret_cast<const TPacketCGAttack*>(data);
ch->GetDesc()->AssembleCRCMagicCube(packMelee->bCRCMagicCubeProcPiece, packMelee->bCRCMagicCubeFilePiece);
LPCHARACTER victim = CHARACTER_MANAGER::instance().Find(packMelee->dwVID);
if (NULL == victim || ch == victim)
return;
switch (victim->GetCharType())
{
case CHAR_TYPE_NPC:
case CHAR_TYPE_WARP:
case CHAR_TYPE_GOTO:
return;
}
if (packMelee->bType > 0)
{
if (false == ch->CheckSkillHitCount(packMelee->bType, victim->GetVID()))
{
return;
}
}
ch->Attack(victim, packMelee->bType);
}
break;
case HEADER_CG_SHOOT:
{
const TPacketCGShoot* const packShoot = reinterpret_cast<const TPacketCGShoot*>(data);
ch->Shoot(packShoot->bType);
}
break;
}
}
int CInputMain::SyncPosition(LPCHARACTER ch, const char * c_pcData, size_t uiBytes)
{
const TPacketCGSyncPosition* pinfo = reinterpret_cast<const TPacketCGSyncPosition*>( c_pcData );
if (uiBytes < pinfo->wSize)
return -1;
int iExtraLen = pinfo->wSize - sizeof(TPacketCGSyncPosition);
if (iExtraLen < 0)
{
SPDLOG_ERROR("invalid packet length (len {} size {} buffer {})", iExtraLen, pinfo->wSize, uiBytes);
ch->GetDesc()->SetPhase(PHASE_CLOSE);
return -1;
}
if (0 != (iExtraLen % sizeof(TPacketCGSyncPositionElement)))
{
SPDLOG_ERROR("invalid packet length {} (name: {})", pinfo->wSize, ch->GetName());
return iExtraLen;
}
int iCount = iExtraLen / sizeof(TPacketCGSyncPositionElement);
if (iCount <= 0)
return iExtraLen;
static const int nCountLimit = 16;
if( iCount > nCountLimit )
{
//LogManager::instance().HackLog( "SYNC_POSITION_HACK", ch );
SPDLOG_ERROR("Too many SyncPosition Count({}) from Name({})", iCount, ch->GetName() );
//ch->GetDesc()->SetPhase(PHASE_CLOSE);
//return -1;
iCount = nCountLimit;
}
TEMP_BUFFER tbuf;
LPBUFFER lpBuf = tbuf.getptr();
TPacketGCSyncPosition * pHeader = (TPacketGCSyncPosition *) buffer_write_peek(lpBuf);
buffer_write_proceed(lpBuf, sizeof(TPacketGCSyncPosition));
const TPacketCGSyncPositionElement* e =
reinterpret_cast<const TPacketCGSyncPositionElement*>(c_pcData + sizeof(TPacketCGSyncPosition));
timeval tvCurTime;
gettimeofday(&tvCurTime, NULL);
for (int i = 0; i < iCount; ++i, ++e)
{
LPCHARACTER victim = CHARACTER_MANAGER::instance().Find(e->dwVID);
if (!victim)
continue;
switch (victim->GetCharType())
{
case CHAR_TYPE_NPC:
case CHAR_TYPE_WARP:
case CHAR_TYPE_GOTO:
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 ·Î µÒ...
if (fDistWithSyncOwner > fLimitDistWithSyncOwner)
{
// g_iSyncHackLimitCount¹ø ±îÁö´Â ºÁÁÜ.
if (ch->GetSyncHackCount() < g_iSyncHackLimitCount)
{
ch->SetSyncHackCount(ch->GetSyncHackCount() + 1);
continue;
}
else
{
LogManager::instance().HackLog( "SYNC_POSITION_HACK", ch );
SPDLOG_ERROR("Too far SyncPosition DistanceWithSyncOwner({})({}) from Name({}) CH({},{}) VICTIM({},{}) SYNC({},{})",
fDistWithSyncOwner, victim->GetName(), ch->GetName(), ch->GetX(), ch->GetY(), victim->GetX(), victim->GetY(),
e->lX, e->lY );
ch->GetDesc()->SetPhase(PHASE_CLOSE);
return -1;
}
}
const float fDist = DISTANCE_SQRT( (victim->GetX() - e->lX) / 100, (victim->GetY() - e->lY) / 100 );
static const int g_lValidSyncInterval = 50 * 1000; // 100ms -> 50ms 2013 09 11 CYH
const timeval &tvLastSyncTime = victim->GetLastSyncTime();
timeval *tvDiff = timediff(&tvCurTime, &tvLastSyncTime);
// SyncPositionÀ» ¾Ç¿ëÇÏ¿© ŸÀ¯Àú¸¦ ÀÌ»óÇÑ °÷À¸·Î º¸³»´Â ÇÙ ¹æ¾îÇϱâ À§ÇÏ¿©,
// °°Àº À¯Àú¸¦ g_lValidSyncInterval ms À̳»¿¡ ´Ù½Ã SyncPositionÇÏ·Á°í Çϸé ÇÙÀ¸·Î °£ÁÖ.
if (tvDiff->tv_sec == 0 && tvDiff->tv_usec < g_lValidSyncInterval)
{
// g_iSyncHackLimitCount¹ø ±îÁö´Â ºÁÁÜ.
if (ch->GetSyncHackCount() < g_iSyncHackLimitCount)
{
ch->SetSyncHackCount(ch->GetSyncHackCount() + 1);
continue;
}
else
{
LogManager::instance().HackLog( "SYNC_POSITION_HACK", ch );
SPDLOG_ERROR("Too often SyncPosition Interval({}ms)({}) from Name({}) VICTIM({},{}) SYNC({},{})",
tvDiff->tv_sec * 1000 + tvDiff->tv_usec / 1000, victim->GetName(), ch->GetName(), victim->GetX(), victim->GetY(),
e->lX, e->lY );
ch->GetDesc()->SetPhase(PHASE_CLOSE);
return -1;
}
}
else if( fDist > 25.0f )
{
LogManager::instance().HackLog( "SYNC_POSITION_HACK", ch );
SPDLOG_ERROR("Too far SyncPosition Distance({})({}) from Name({}) CH({},{}) VICTIM({},{}) SYNC({},{})",
fDist, victim->GetName(), ch->GetName(), ch->GetX(), ch->GetY(), victim->GetX(), victim->GetY(),
e->lX, e->lY );
ch->GetDesc()->SetPhase(PHASE_CLOSE);
return -1;
}
else
{
victim->SetLastSyncTime(tvCurTime);
victim->Sync(e->lX, e->lY);
buffer_write(lpBuf, e, sizeof(TPacketCGSyncPositionElement));
}
}
if (buffer_size(lpBuf) != sizeof(TPacketGCSyncPosition))
{
pHeader->bHeader = HEADER_GC_SYNC_POSITION;
pHeader->wSize = buffer_size(lpBuf);
ch->PacketAround(buffer_read_peek(lpBuf), buffer_size(lpBuf), ch);
}
return iExtraLen;
}
void CInputMain::FlyTarget(LPCHARACTER ch, const char * pcData, BYTE bHeader)
{
TPacketCGFlyTargeting * p = (TPacketCGFlyTargeting *) pcData;
ch->FlyTarget(p->dwTargetVID, p->x, p->y, bHeader);
}
void CInputMain::UseSkill(LPCHARACTER ch, const char * pcData)
{
TPacketCGUseSkill * p = (TPacketCGUseSkill *) pcData;
ch->UseSkill(p->dwVnum, CHARACTER_MANAGER::instance().Find(p->dwVID));
}
void CInputMain::ScriptButton(LPCHARACTER ch, const void* c_pData)
{
TPacketCGScriptButton * p = (TPacketCGScriptButton *) c_pData;
SPDLOG_DEBUG("QUEST ScriptButton pid {} idx {}", ch->GetPlayerID(), p->idx);
quest::PC* pc = quest::CQuestManager::instance().GetPCForce(ch->GetPlayerID());
if (pc && pc->IsConfirmWait())
{
quest::CQuestManager::instance().Confirm(ch->GetPlayerID(), quest::CONFIRM_TIMEOUT);
}
else if (p->idx & 0x80000000)
{
quest::CQuestManager::Instance().QuestInfo(ch->GetPlayerID(), p->idx & 0x7fffffff);
}
else
{
quest::CQuestManager::Instance().QuestButton(ch->GetPlayerID(), p->idx);
}
}
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) // ´ÙÀ½ ¹öÆ°¿¡ ´ëÇÑ ÀÀ´äÀ¸·Î ¿Â ÆÐŶÀÎ °æ¿ì
{
quest::CQuestManager::Instance().Resume(ch->GetPlayerID());
}
else // ¼±Åà ¹öÆ°À» °ñ¶ó¼­ ¿Â ÆÐŶÀÎ °æ¿ì
{
quest::CQuestManager::Instance().Select(ch->GetPlayerID(), p->answer);
}
}
// SCRIPT_SELECT_ITEM
void CInputMain::ScriptSelectItem(LPCHARACTER ch, const void* c_pData)
{
TPacketCGScriptSelectItem* p = (TPacketCGScriptSelectItem*) c_pData;
SPDLOG_DEBUG("QUEST ScriptSelectItem pid {} answer {}", ch->GetPlayerID(), p->selection);
quest::CQuestManager::Instance().SelectItem(ch->GetPlayerID(), p->selection);
}
// END_OF_SCRIPT_SELECT_ITEM
void CInputMain::QuestInputString(LPCHARACTER ch, const void* c_pData)
{
TPacketCGQuestInputString * p = (TPacketCGQuestInputString*) c_pData;
char msg[65];
strlcpy(msg, p->msg, sizeof(msg));
SPDLOG_DEBUG("QUEST InputString pid {} msg {}", ch->GetPlayerID(), msg);
quest::CQuestManager::Instance().Input(ch->GetPlayerID(), msg);
}
void CInputMain::QuestConfirm(LPCHARACTER ch, const void* c_pData)
{
TPacketCGQuestConfirm* p = (TPacketCGQuestConfirm*) c_pData;
LPCHARACTER ch_wait = CHARACTER_MANAGER::instance().FindByPID(p->requestPID);
if (p->answer)
p->answer = quest::CONFIRM_YES;
SPDLOG_DEBUG("QuestConfirm from {} pid {} name {} answer {}", ch->GetName(), p->requestPID, (ch_wait)?ch_wait->GetName():"", p->answer);
if (ch_wait)
{
quest::CQuestManager::Instance().Confirm(ch_wait->GetPlayerID(), (quest::EQuestConfirmType) p->answer, ch->GetPlayerID());
}
}
void CInputMain::Target(LPCHARACTER ch, const char * pcData)
{
TPacketCGTarget * p = (TPacketCGTarget *) pcData;
building::LPOBJECT pkObj = building::CManager::instance().FindObjectByVID(p->dwVID);
if (pkObj)
{
TPacketGCTarget pckTarget;
pckTarget.header = HEADER_GC_TARGET;
pckTarget.dwVID = p->dwVID;
ch->GetDesc()->Packet(&pckTarget, sizeof(TPacketGCTarget));
}
else
ch->SetTarget(CHARACTER_MANAGER::instance().Find(p->dwVID));
}
void CInputMain::Warp(LPCHARACTER ch, const char * pcData)
{
ch->WarpEnd();
}
void CInputMain::SafeboxCheckin(LPCHARACTER ch, const char * c_pData)
{
if (quest::CQuestManager::instance().GetPCForce(ch->GetPlayerID())->IsRunning() == true)
return;
TPacketCGSafeboxCheckin * p = (TPacketCGSafeboxCheckin *) c_pData;
if (!ch->CanHandleItem())
return;
CSafebox * pkSafebox = ch->GetSafebox();
LPITEM pkItem = ch->GetItem(p->ItemPos);
if (!pkSafebox || !pkItem)
return;
if (pkItem->GetCell() >= INVENTORY_MAX_NUM && IS_SET(pkItem->GetFlag(), ITEM_FLAG_IRREMOVABLE))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC3\xA2\xB0\xED> \xC3\xA2\xB0\xED\xB7\xCE \xBF\xC5\xB1\xE6 \xBC\xF6 \xBE\xF8\xB4\xC2 \xBE\xC6\xC0\xCC\xC5\xDB \xC0\xD4\xB4\xCF\xB4\xD9."));
return;
}
if (!pkSafebox->IsEmpty(p->bSafePos, pkItem->GetSize()))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC3\xA2\xB0\xED> \xBF\xC5\xB1\xE6 \xBC\xF6 \xBE\xF8\xB4\xC2 \xC0\xA7\xC4\xA1\xC0\xD4\xB4\xCF\xB4\xD9."));
return;
}
if (pkItem->GetVnum() == UNIQUE_ITEM_SAFEBOX_EXPAND)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC3\xA2\xB0\xED> \xC0\xCC \xBE\xC6\xC0\xCC\xC5\xDB\xC0\xBA \xB3\xD6\xC0\xBB \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return;
}
if( IS_SET(pkItem->GetAntiFlag(), ITEM_ANTIFLAG_SAFEBOX) )
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC3\xA2\xB0\xED> \xC0\xCC \xBE\xC6\xC0\xCC\xC5\xDB\xC0\xBA \xB3\xD6\xC0\xBB \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return;
}
if (true == pkItem->isLocked())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC3\xA2\xB0\xED> \xC0\xCC \xBE\xC6\xC0\xCC\xC5\xDB\xC0\xBA \xB3\xD6\xC0\xBB \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return;
}
pkItem->RemoveFromCharacter();
if (!pkItem->IsDragonSoul())
ch->SyncQuickslot(QUICKSLOT_TYPE_ITEM, p->ItemPos.cell, 255);
pkSafebox->Add(p->bSafePos, pkItem);
char szHint[128];
snprintf(szHint, sizeof(szHint), "%s %u", pkItem->GetName(), pkItem->GetCount());
LogManager::instance().ItemLog(ch, pkItem, "SAFEBOX PUT", szHint);
}
void CInputMain::SafeboxCheckout(LPCHARACTER ch, const char * c_pData, bool bMall)
{
TPacketCGSafeboxCheckout * p = (TPacketCGSafeboxCheckout *) c_pData;
if (!ch->CanHandleItem())
return;
CSafebox * pkSafebox;
if (bMall)
pkSafebox = ch->GetMall();
else
pkSafebox = ch->GetSafebox();
if (!pkSafebox)
return;
LPITEM pkItem = pkSafebox->Get(p->bSafePos);
if (!pkItem)
return;
if (!ch->IsEmptyItemGrid(p->ItemPos, pkItem->GetSize()))
return;
// ¾ÆÀÌÅÛ ¸ô¿¡¼­ Àκ¥À¸·Î ¿Å±â´Â ºÎºÐ¿¡¼­ ¿ëÈ¥¼® Ư¼ö ó¸®
// (¸ô¿¡¼­ ¸¸µå´Â ¾ÆÀÌÅÛÀº item_proto¿¡ Á¤Àǵȴë·Î ¼Ó¼ºÀÌ ºÙ±â ¶§¹®¿¡,
// ¿ëÈ¥¼®ÀÇ °æ¿ì, ÀÌ Ã³¸®¸¦ ÇÏÁö ¾ÊÀ¸¸é ¼Ó¼ºÀÌ Çϳªµµ ºÙÁö ¾Ê°Ô µÈ´Ù.)
if (pkItem->IsDragonSoul())
{
if (bMall)
{
DSManager::instance().DragonSoulItemInitialize(pkItem);
}
if (DRAGON_SOUL_INVENTORY != p->ItemPos.window_type)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC3\xA2\xB0\xED> \xBF\xC5\xB1\xE6 \xBC\xF6 \xBE\xF8\xB4\xC2 \xC0\xA7\xC4\xA1\xC0\xD4\xB4\xCF\xB4\xD9."));
return;
}
TItemPos DestPos = p->ItemPos;
if (!DSManager::instance().IsValidCellForThisItem(pkItem, DestPos))
{
int iCell = ch->GetEmptyDragonSoulInventory(pkItem);
if (iCell < 0)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC3\xA2\xB0\xED> \xBF\xC5\xB1\xE6 \xBC\xF6 \xBE\xF8\xB4\xC2 \xC0\xA7\xC4\xA1\xC0\xD4\xB4\xCF\xB4\xD9."));
return ;
}
DestPos = TItemPos (DRAGON_SOUL_INVENTORY, iCell);
}
pkSafebox->Remove(p->bSafePos);
pkItem->AddToCharacter(ch, DestPos);
ITEM_MANAGER::instance().FlushDelayedSave(pkItem);
}
else
{
if (DRAGON_SOUL_INVENTORY == p->ItemPos.window_type)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC3\xA2\xB0\xED> \xBF\xC5\xB1\xE6 \xBC\xF6 \xBE\xF8\xB4\xC2 \xC0\xA7\xC4\xA1\xC0\xD4\xB4\xCF\xB4\xD9."));
return;
}
pkSafebox->Remove(p->bSafePos);
if (bMall)
{
if (NULL == pkItem->GetProto())
{
SPDLOG_ERROR("pkItem->GetProto() == NULL (id : {})",pkItem->GetID());
return ;
}
// 100% È®·ü·Î ¼Ó¼ºÀÌ ºÙ¾î¾ß Çϴµ¥ ¾È ºÙ¾îÀÖ´Ù¸é »õ·Î ºÙÈù´Ù. ...............
if (100 == pkItem->GetProto()->bAlterToMagicItemPct && 0 == pkItem->GetAttributeCount())
{
pkItem->AlterToMagicItem();
}
}
pkItem->AddToCharacter(ch, p->ItemPos);
ITEM_MANAGER::instance().FlushDelayedSave(pkItem);
}
DWORD dwID = pkItem->GetID();
db_clientdesc->DBPacketHeader(HEADER_GD_ITEM_FLUSH, 0, sizeof(DWORD));
db_clientdesc->Packet(&dwID, sizeof(DWORD));
char szHint[128];
snprintf(szHint, sizeof(szHint), "%s %u", pkItem->GetName(), pkItem->GetCount());
if (bMall)
LogManager::instance().ItemLog(ch, pkItem, "MALL GET", szHint);
else
LogManager::instance().ItemLog(ch, pkItem, "SAFEBOX GET", szHint);
}
void CInputMain::SafeboxItemMove(LPCHARACTER ch, const char * data)
{
struct command_item_move * pinfo = (struct command_item_move *) data;
if (!ch->CanHandleItem())
return;
if (!ch->GetSafebox())
return;
ch->GetSafebox()->MoveItem(pinfo->Cell.cell, pinfo->CellTo.cell, pinfo->count);
}
// PARTY_JOIN_BUG_FIX
void CInputMain::PartyInvite(LPCHARACTER ch, const char * c_pData)
{
if (ch->GetArena())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB4\xEB\xB7\xC3\xC0\xE5\xBF\xA1\xBC\xAD \xBB\xE7\xBF\xEB\xC7\xCF\xBD\xC7 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return;
}
TPacketCGPartyInvite * p = (TPacketCGPartyInvite*) c_pData;
LPCHARACTER pInvitee = CHARACTER_MANAGER::instance().Find(p->vid);
if (!pInvitee || !ch->GetDesc() || !pInvitee->GetDesc())
{
SPDLOG_ERROR("PARTY Cannot find invited character");
return;
}
ch->PartyInvite(pInvitee);
}
void CInputMain::PartyInviteAnswer(LPCHARACTER ch, const char * c_pData)
{
if (ch->GetArena())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB4\xEB\xB7\xC3\xC0\xE5\xBF\xA1\xBC\xAD \xBB\xE7\xBF\xEB\xC7\xCF\xBD\xC7 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return;
}
TPacketCGPartyInviteAnswer * p = (TPacketCGPartyInviteAnswer*) c_pData;
LPCHARACTER pInviter = CHARACTER_MANAGER::instance().Find(p->leader_vid);
// 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."));
else if (!p->accept)
pInviter->PartyInviteDeny(ch->GetPlayerID());
else
pInviter->PartyInviteAccept(ch);
}
// END_OF_PARTY_JOIN_BUG_FIX
void CInputMain::PartySetState(LPCHARACTER ch, const char* c_pData)
{
if (!CPartyManager::instance().IsEnablePCParty())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC6\xC4\xC6\xBC> \xBC\xAD\xB9\xF6 \xB9\xAE\xC1\xA6\xB7\xCE \xC6\xC4\xC6\xBC \xB0\xFC\xB7\xC3 \xC3\xB3\xB8\xAE\xB8\xA6 \xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return;
}
TPacketCGPartySetState* p = (TPacketCGPartySetState*) c_pData;
if (!ch->GetParty())
return;
if (ch->GetParty()->GetLeaderPID() != ch->GetPlayerID())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC6\xC4\xC6\xBC> \xB8\xAE\xB4\xF5\xB8\xB8 \xBA\xAF\xB0\xE6\xC7\xD2 \xBC\xF6 \xC0\xD6\xBD\xC0\xB4\xCF\xB4\xD9."));
return;
}
if (!ch->GetParty()->IsMember(p->pid))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC6\xC4\xC6\xBC> \xBB\xF3\xC5\xC2\xB8\xA6 \xBA\xAF\xB0\xE6\xC7\xCF\xB7\xC1\xB4\xC2 \xBB\xE7\xB6\xF7\xC0\xCC \xC6\xC4\xC6\xBC\xBF\xF8\xC0\xCC \xBE\xC6\xB4\xD5\xB4\xCF\xB4\xD9."));
return;
}
DWORD pid = p->pid;
SPDLOG_DEBUG("PARTY SetRole pid {} to role {} state {}", pid, p->byRole, p->flag ? "on" : "off");
switch (p->byRole)
{
case PARTY_ROLE_NORMAL:
break;
case PARTY_ROLE_ATTACKER:
case PARTY_ROLE_TANKER:
case PARTY_ROLE_BUFFER:
case PARTY_ROLE_SKILL_MASTER:
case PARTY_ROLE_HASTE:
case PARTY_ROLE_DEFENDER:
if (ch->GetParty()->SetRole(pid, p->byRole, p->flag))
{
TPacketPartyStateChange pack;
pack.dwLeaderPID = ch->GetPlayerID();
pack.dwPID = p->pid;
pack.bRole = p->byRole;
pack.bFlag = p->flag;
db_clientdesc->DBPacket(HEADER_GD_PARTY_STATE_CHANGE, 0, &pack, sizeof(pack));
}
/* else
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC6\xC4\xC6\xBC> \xBE\xEE\xC5\xC2\xC4\xBF \xBC\xB3\xC1\xA4\xBF\xA1 \xBD\xC7\xC6\xD0\xC7\xCF\xBF\xB4\xBD\xC0\xB4\xCF\xB4\xD9.")); */
break;
default:
SPDLOG_ERROR("wrong byRole in PartySetState Packet name {} state {}", ch->GetName(), p->byRole);
break;
}
}
void CInputMain::PartyRemove(LPCHARACTER ch, const char* c_pData)
{
if (ch->GetArena())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB4\xEB\xB7\xC3\xC0\xE5\xBF\xA1\xBC\xAD \xBB\xE7\xBF\xEB\xC7\xCF\xBD\xC7 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return;
}
if (!CPartyManager::instance().IsEnablePCParty())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC6\xC4\xC6\xBC> \xBC\xAD\xB9\xF6 \xB9\xAE\xC1\xA6\xB7\xCE \xC6\xC4\xC6\xBC \xB0\xFC\xB7\xC3 \xC3\xB3\xB8\xAE\xB8\xA6 \xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return;
}
if (ch->GetDungeon())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC6\xC4\xC6\xBC> \xB4\xF8\xC0\xFC \xBE\xC8\xBF\xA1\xBC\xAD\xB4\xC2 \xC6\xC4\xC6\xBC\xBF\xA1\xBC\xAD \xC3\xDF\xB9\xE6\xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return;
}
TPacketCGPartyRemove* p = (TPacketCGPartyRemove*) c_pData;
if (!ch->GetParty())
return;
LPPARTY pParty = ch->GetParty();
if (pParty->GetLeaderPID() == ch->GetPlayerID())
{
if (ch->GetDungeon())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC6\xC4\xC6\xBC> \xB4\xF8\xC1\xAF\xB3\xBB\xBF\xA1\xBC\xAD\xB4\xC2 \xC6\xC4\xC6\xBC\xBF\xF8\xC0\xBB \xC3\xDF\xB9\xE6\xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
}
else
{
// leader can remove any member
if (p->pid == ch->GetPlayerID() || pParty->GetMemberCount() == 2)
{
// party disband
CPartyManager::instance().DeleteParty(pParty);
}
else
{
LPCHARACTER B = CHARACTER_MANAGER::instance().FindByPID(p->pid);
if (B)
{
//pParty->SendPartyRemoveOneToAll(B);
B->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC6\xC4\xC6\xBC> \xC6\xC4\xC6\xBC\xBF\xA1\xBC\xAD \xC3\xDF\xB9\xE6\xB4\xE7\xC7\xCF\xBC\xCC\xBD\xC0\xB4\xCF\xB4\xD9."));
//pParty->Unlink(B);
//CPartyManager::instance().SetPartyMember(B->GetPlayerID(), NULL);
}
pParty->Quit(p->pid);
}
}
}
else
{
// otherwise, only remove itself
if (p->pid == ch->GetPlayerID())
{
if (ch->GetDungeon())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC6\xC4\xC6\xBC> \xB4\xF8\xC1\xAF\xB3\xBB\xBF\xA1\xBC\xAD\xB4\xC2 \xC6\xC4\xC6\xBC\xB8\xA6 \xB3\xAA\xB0\xA5 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
}
else
{
if (pParty->GetMemberCount() == 2)
{
// party disband
CPartyManager::instance().DeleteParty(pParty);
}
else
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC6\xC4\xC6\xBC> \xC6\xC4\xC6\xBC\xBF\xA1\xBC\xAD \xB3\xAA\xB0\xA1\xBC\xCC\xBD\xC0\xB4\xCF\xB4\xD9."));
//pParty->SendPartyRemoveOneToAll(ch);
pParty->Quit(ch->GetPlayerID());
//pParty->SendPartyRemoveAllToOne(ch);
//CPartyManager::instance().SetPartyMember(ch->GetPlayerID(), NULL);
}
}
}
else
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC6\xC4\xC6\xBC> \xB4\xD9\xB8\xA5 \xC6\xC4\xC6\xBC\xBF\xF8\xC0\xBB \xC5\xBB\xC5\xF0\xBD\xC3\xC5\xB3 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
}
}
}
void CInputMain::AnswerMakeGuild(LPCHARACTER ch, const char* c_pData)
{
TPacketCGAnswerMakeGuild* p = (TPacketCGAnswerMakeGuild*) c_pData;
if (ch->GetGold() < 200000)
return;
if (get_global_time() - ch->GetQuestFlag("guild_manage.new_disband_time") <
CGuildManager::instance().GetDisbandDelay())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xC7\xD8\xBB\xEA\xC7\xD1 \xC8\xC4 %d\xC0\xCF \xC0\xCC\xB3\xBB\xBF\xA1\xB4\xC2 \xB1\xE6\xB5\xE5\xB8\xA6 \xB8\xB8\xB5\xE9 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."),
quest::CQuestManager::instance().GetEventFlag("guild_disband_delay"));
return;
}
if (get_global_time() - ch->GetQuestFlag("guild_manage.new_withdraw_time") <
CGuildManager::instance().GetWithdrawDelay())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xC5\xBB\xC5\xF0\xC7\xD1 \xC8\xC4 %d\xC0\xCF \xC0\xCC\xB3\xBB\xBF\xA1\xB4\xC2 \xB1\xE6\xB5\xE5\xB8\xA6 \xB8\xB8\xB5\xE9 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."),
quest::CQuestManager::instance().GetEventFlag("guild_withdraw_delay"));
return;
}
if (ch->GetGuild())
return;
CGuildManager& gm = CGuildManager::instance();
TGuildCreateParameter cp;
memset(&cp, 0, sizeof(cp));
cp.master = ch;
strlcpy(cp.name, p->guild_name, sizeof(cp.name));
if (cp.name[0] == 0 || !check_name(cp.name))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xC0\xFB\xC7\xD5\xC7\xCF\xC1\xF6 \xBE\xCA\xC0\xBA \xB1\xE6\xB5\xE5 \xC0\xCC\xB8\xA7 \xC0\xD4\xB4\xCF\xB4\xD9."));
return;
}
DWORD dwGuildID = gm.CreateGuild(cp);
if (dwGuildID)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> [%s] \xB1\xE6\xB5\xE5\xB0\xA1 \xBB\xFD\xBC\xBA\xB5\xC7\xBE\xFA\xBD\xC0\xB4\xCF\xB4\xD9."), cp.name);
int GuildCreateFee;
if (LC_IsBrazil())
{
GuildCreateFee = 500000;
}
else
{
GuildCreateFee = 200000;
}
ch->PointChange(POINT_GOLD, -GuildCreateFee);
DBManager::instance().SendMoneyLog(MONEY_LOG_GUILD, ch->GetPlayerID(), -GuildCreateFee);
char Log[128];
snprintf(Log, sizeof(Log), "GUILD_NAME %s MASTER %s", cp.name, ch->GetName());
LogManager::instance().CharLog(ch, 0, "MAKE_GUILD", Log);
if (g_iUseLocale)
ch->RemoveSpecifyItem(GUILD_CREATE_ITEM_VNUM, 1);
//ch->SendGuildName(dwGuildID);
}
else
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB1\xE6\xB5\xE5 \xBB\xFD\xBC\xBA\xBF\xA1 \xBD\xC7\xC6\xD0\xC7\xCF\xBF\xB4\xBD\xC0\xB4\xCF\xB4\xD9."));
}
void CInputMain::PartyUseSkill(LPCHARACTER ch, const char* c_pData)
{
TPacketCGPartyUseSkill* p = (TPacketCGPartyUseSkill*) c_pData;
if (!ch->GetParty())
return;
if (ch->GetPlayerID() != ch->GetParty()->GetLeaderPID())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC6\xC4\xC6\xBC> \xC6\xC4\xC6\xBC \xB1\xE2\xBC\xFA\xC0\xBA \xC6\xC4\xC6\xBC\xC0\xE5\xB8\xB8 \xBB\xE7\xBF\xEB\xC7\xD2 \xBC\xF6 \xC0\xD6\xBD\xC0\xB4\xCF\xB4\xD9."));
return;
}
switch (p->bySkillIndex)
{
case PARTY_SKILL_HEAL:
ch->GetParty()->HealParty();
break;
case PARTY_SKILL_WARP:
{
LPCHARACTER pch = CHARACTER_MANAGER::instance().Find(p->vid);
if (pch)
ch->GetParty()->SummonToLeader(pch->GetPlayerID());
else
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xC6\xC4\xC6\xBC> \xBC\xD2\xC8\xAF\xC7\xCF\xB7\xC1\xB4\xC2 \xB4\xEB\xBB\xF3\xC0\xBB \xC3\xA3\xC0\xBB \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
}
break;
}
}
void CInputMain::PartyParameter(LPCHARACTER ch, const char * c_pData)
{
TPacketCGPartyParameter * p = (TPacketCGPartyParameter *) c_pData;
if (ch->GetParty())
ch->GetParty()->SetParameter(p->bDistributeMode);
}
size_t GetSubPacketSize(const GUILD_SUBHEADER_CG& header)
{
switch (header)
{
case GUILD_SUBHEADER_CG_DEPOSIT_MONEY: return sizeof(int);
case GUILD_SUBHEADER_CG_WITHDRAW_MONEY: return sizeof(int);
case GUILD_SUBHEADER_CG_ADD_MEMBER: return sizeof(DWORD);
case GUILD_SUBHEADER_CG_REMOVE_MEMBER: return sizeof(DWORD);
case GUILD_SUBHEADER_CG_CHANGE_GRADE_NAME: return 10;
case GUILD_SUBHEADER_CG_CHANGE_GRADE_AUTHORITY: return sizeof(BYTE) + sizeof(BYTE);
case GUILD_SUBHEADER_CG_OFFER: return sizeof(DWORD);
case GUILD_SUBHEADER_CG_CHARGE_GSP: return sizeof(int);
case GUILD_SUBHEADER_CG_POST_COMMENT: return 1;
case GUILD_SUBHEADER_CG_DELETE_COMMENT: return sizeof(DWORD);
case GUILD_SUBHEADER_CG_REFRESH_COMMENT: return 0;
case GUILD_SUBHEADER_CG_CHANGE_MEMBER_GRADE: return sizeof(DWORD) + sizeof(BYTE);
case GUILD_SUBHEADER_CG_USE_SKILL: return sizeof(TPacketCGGuildUseSkill);
case GUILD_SUBHEADER_CG_CHANGE_MEMBER_GENERAL: return sizeof(DWORD) + sizeof(BYTE);
case GUILD_SUBHEADER_CG_GUILD_INVITE_ANSWER: return sizeof(DWORD) + sizeof(BYTE);
}
return 0;
}
int CInputMain::Guild(LPCHARACTER ch, const char * data, size_t uiBytes)
{
if (uiBytes < sizeof(TPacketCGGuild))
return -1;
const TPacketCGGuild* p = reinterpret_cast<const TPacketCGGuild*>(data);
const char* c_pData = data + sizeof(TPacketCGGuild);
uiBytes -= sizeof(TPacketCGGuild);
const GUILD_SUBHEADER_CG SubHeader = static_cast<GUILD_SUBHEADER_CG>(p->subheader);
const size_t SubPacketLen = GetSubPacketSize(SubHeader);
if (uiBytes < SubPacketLen)
{
return -1;
}
CGuild* pGuild = ch->GetGuild();
if (NULL == pGuild)
{
if (SubHeader != GUILD_SUBHEADER_CG_GUILD_INVITE_ANSWER)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB1\xE6\xB5\xE5\xBF\xA1 \xBC\xD3\xC7\xD8\xC0\xD6\xC1\xF6 \xBE\xCA\xBD\xC0\xB4\xCF\xB4\xD9."));
return SubPacketLen;
}
}
switch (SubHeader)
{
case GUILD_SUBHEADER_CG_DEPOSIT_MONEY:
{
// by mhh : ±æµåÀÚ±ÝÀº ´çºÐ°£ ³ÖÀ» ¼ö ¾ø´Ù.
return SubPacketLen;
const int gold = std::min(*reinterpret_cast<const int*>(c_pData), __deposit_limit());
if (gold < 0)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xC0\xDF\xB8\xF8\xB5\xC8 \xB1\xDD\xBE\xD7\xC0\xD4\xB4\xCF\xB4\xD9."));
return SubPacketLen;
}
if (ch->GetGold() < gold)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB0\xA1\xC1\xF6\xB0\xED \xC0\xD6\xB4\xC2 \xB5\xB7\xC0\xCC \xBA\xCE\xC1\xB7\xC7\xD5\xB4\xCF\xB4\xD9."));
return SubPacketLen;
}
pGuild->RequestDepositMoney(ch, gold);
}
return SubPacketLen;
case GUILD_SUBHEADER_CG_WITHDRAW_MONEY:
{
// by mhh : ±æµåÀÚ±ÝÀº ´çºÐ°£ »¬ ¼ö ¾ø´Ù.
return SubPacketLen;
const int gold = std::min(*reinterpret_cast<const int*>(c_pData), 500000);
if (gold < 0)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xC0\xDF\xB8\xF8\xB5\xC8 \xB1\xDD\xBE\xD7\xC0\xD4\xB4\xCF\xB4\xD9."));
return SubPacketLen;
}
pGuild->RequestWithdrawMoney(ch, gold);
}
return SubPacketLen;
case GUILD_SUBHEADER_CG_ADD_MEMBER:
{
const DWORD vid = *reinterpret_cast<const DWORD*>(c_pData);
LPCHARACTER newmember = CHARACTER_MANAGER::instance().Find(vid);
if (!newmember)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB1\xD7\xB7\xAF\xC7\xD1 \xBB\xE7\xB6\xF7\xC0\xBB \xC3\xA3\xC0\xBB \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return SubPacketLen;
}
if (!ch->IsPC())
return SubPacketLen;
if (LC_IsCanada() == true)
{
if (newmember->GetQuestFlag("change_guild_master.be_other_member") > get_global_time())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xBE\xC6\xC1\xF7 \xB0\xA1\xC0\xD4\xC7\xD2 \xBC\xF6 \xBE\xF8\xB4\xC2 \xC4\xB3\xB8\xAF\xC5\xCD\xC0\xD4\xB4\xCF\xB4\xD9"));
return SubPacketLen;
}
}
pGuild->Invite(ch, newmember);
}
return SubPacketLen;
case GUILD_SUBHEADER_CG_REMOVE_MEMBER:
{
if (pGuild->UnderAnyWar() != 0)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB1\xE6\xB5\xE5\xC0\xFC \xC1\xDF\xBF\xA1\xB4\xC2 \xB1\xE6\xB5\xE5\xBF\xF8\xC0\xBB \xC5\xBB\xC5\xF0\xBD\xC3\xC5\xB3 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return SubPacketLen;
}
const DWORD pid = *reinterpret_cast<const DWORD*>(c_pData);
const TGuildMember* m = pGuild->GetMember(ch->GetPlayerID());
if (NULL == m)
return -1;
LPCHARACTER member = CHARACTER_MANAGER::instance().FindByPID(pid);
if (member)
{
if (member->GetGuild() != pGuild)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xBB\xF3\xB4\xEB\xB9\xE6\xC0\xCC \xB0\xB0\xC0\xBA \xB1\xE6\xB5\xE5\xB0\xA1 \xBE\xC6\xB4\xD5\xB4\xCF\xB4\xD9."));
return SubPacketLen;
}
if (!pGuild->HasGradeAuth(m->grade, GUILD_AUTH_REMOVE_MEMBER))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB1\xE6\xB5\xE5\xBF\xF8\xC0\xBB \xB0\xAD\xC1\xA6 \xC5\xBB\xC5\xF0 \xBD\xC3\xC5\xB3 \xB1\xC7\xC7\xD1\xC0\xCC \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return SubPacketLen;
}
member->SetQuestFlag("guild_manage.new_withdraw_time", get_global_time());
pGuild->RequestRemoveMember(member->GetPlayerID());
if (LC_IsBrazil() == true)
{
DBManager::instance().Query("REPLACE INTO guild_invite_limit VALUES(%d, %d)", pGuild->GetID(), get_global_time());
}
}
else
{
if (!pGuild->HasGradeAuth(m->grade, GUILD_AUTH_REMOVE_MEMBER))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB1\xE6\xB5\xE5\xBF\xF8\xC0\xBB \xB0\xAD\xC1\xA6 \xC5\xBB\xC5\xF0 \xBD\xC3\xC5\xB3 \xB1\xC7\xC7\xD1\xC0\xCC \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return SubPacketLen;
}
if (pGuild->RequestRemoveMember(pid))
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB1\xE6\xB5\xE5\xBF\xF8\xC0\xBB \xB0\xAD\xC1\xA6 \xC5\xBB\xC5\xF0 \xBD\xC3\xC4\xD7\xBD\xC0\xB4\xCF\xB4\xD9."));
else
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB1\xD7\xB7\xAF\xC7\xD1 \xBB\xE7\xB6\xF7\xC0\xBB \xC3\xA3\xC0\xBB \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
}
}
return SubPacketLen;
case GUILD_SUBHEADER_CG_CHANGE_GRADE_NAME:
{
char gradename[GUILD_GRADE_NAME_MAX_LEN + 1];
strlcpy(gradename, c_pData + 1, sizeof(gradename));
const TGuildMember * m = pGuild->GetMember(ch->GetPlayerID());
if (NULL == m)
return -1;
if (m->grade != GUILD_LEADER_GRADE)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xC1\xF7\xC0\xA7 \xC0\xCC\xB8\xA7\xC0\xBB \xBA\xAF\xB0\xE6\xC7\xD2 \xB1\xC7\xC7\xD1\xC0\xCC \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
}
else if (*c_pData == GUILD_LEADER_GRADE)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB1\xE6\xB5\xE5\xC0\xE5\xC0\xC7 \xC1\xF7\xC0\xA7 \xC0\xCC\xB8\xA7\xC0\xBA \xBA\xAF\xB0\xE6\xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
}
else if (!check_name(gradename))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xC0\xFB\xC7\xD5\xC7\xCF\xC1\xF6 \xBE\xCA\xC0\xBA \xC1\xF7\xC0\xA7 \xC0\xCC\xB8\xA7 \xC0\xD4\xB4\xCF\xB4\xD9."));
}
else
{
pGuild->ChangeGradeName(*c_pData, gradename);
}
}
return SubPacketLen;
case GUILD_SUBHEADER_CG_CHANGE_GRADE_AUTHORITY:
{
const TGuildMember* m = pGuild->GetMember(ch->GetPlayerID());
if (NULL == m)
return -1;
if (m->grade != GUILD_LEADER_GRADE)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xC1\xF7\xC0\xA7 \xB1\xC7\xC7\xD1\xC0\xBB \xBA\xAF\xB0\xE6\xC7\xD2 \xB1\xC7\xC7\xD1\xC0\xCC \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
}
else if (*c_pData == GUILD_LEADER_GRADE)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB1\xE6\xB5\xE5\xC0\xE5\xC0\xC7 \xB1\xC7\xC7\xD1\xC0\xBA \xBA\xAF\xB0\xE6\xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
}
else
{
pGuild->ChangeGradeAuth(*c_pData, *(c_pData + 1));
}
}
return SubPacketLen;
case GUILD_SUBHEADER_CG_OFFER:
{
DWORD offer = *reinterpret_cast<const DWORD*>(c_pData);
if (pGuild->GetLevel() >= GUILD_MAX_LEVEL && LC_IsHongKong() == false)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB1\xE6\xB5\xE5\xB0\xA1 \xC0\xCC\xB9\xCC \xC3\xD6\xB0\xED \xB7\xB9\xBA\xA7\xC0\xD4\xB4\xCF\xB4\xD9."));
}
else
{
offer /= 100;
offer *= 100;
if (pGuild->OfferExp(ch, offer))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> %u\xC0\xC7 \xB0\xE6\xC7\xE8\xC4\xA1\xB8\xA6 \xC5\xF5\xC0\xDA\xC7\xCF\xBF\xB4\xBD\xC0\xB4\xCF\xB4\xD9."), offer);
}
else
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB0\xE6\xC7\xE8\xC4\xA1 \xC5\xF5\xC0\xDA\xBF\xA1 \xBD\xC7\xC6\xD0\xC7\xCF\xBF\xB4\xBD\xC0\xB4\xCF\xB4\xD9."));
}
}
}
return SubPacketLen;
case GUILD_SUBHEADER_CG_CHARGE_GSP:
{
const int offer = *reinterpret_cast<const int*>(c_pData);
const int gold = offer * 100;
if (offer < 0 || gold < offer || gold < 0 || ch->GetGold() < gold)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB5\xB7\xC0\xCC \xBA\xCE\xC1\xB7\xC7\xD5\xB4\xCF\xB4\xD9."));
return SubPacketLen;
}
if (!pGuild->ChargeSP(ch, offer))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xBF\xEB\xBD\xC5\xB7\xC2 \xC8\xB8\xBA\xB9\xBF\xA1 \xBD\xC7\xC6\xD0\xC7\xCF\xBF\xB4\xBD\xC0\xB4\xCF\xB4\xD9."));
}
}
return SubPacketLen;
case GUILD_SUBHEADER_CG_POST_COMMENT:
{
const size_t length = *c_pData;
if (length > GUILD_COMMENT_MAX_LEN)
{
// À߸øµÈ ±æÀÌ.. ²÷¾îÁÖÀÚ.
SPDLOG_ERROR("POST_COMMENT: {} comment too long (length: {})", ch->GetName(), length);
ch->GetDesc()->SetPhase(PHASE_CLOSE);
return -1;
}
if (uiBytes < 1 + length)
return -1;
const TGuildMember* m = pGuild->GetMember(ch->GetPlayerID());
if (NULL == m)
return -1;
if (length && !pGuild->HasGradeAuth(m->grade, GUILD_AUTH_NOTICE) && *(c_pData + 1) == '!')
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB0\xF8\xC1\xF6\xB1\xDB\xC0\xBB \xC0\xDB\xBC\xBA\xC7\xD2 \xB1\xC7\xC7\xD1\xC0\xCC \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
}
else
{
std::string str(c_pData + 1, length);
pGuild->AddComment(ch, str);
}
return (1 + length);
}
case GUILD_SUBHEADER_CG_DELETE_COMMENT:
{
const DWORD comment_id = *reinterpret_cast<const DWORD*>(c_pData);
pGuild->DeleteComment(ch, comment_id);
}
return SubPacketLen;
case GUILD_SUBHEADER_CG_REFRESH_COMMENT:
pGuild->RefreshComment(ch);
return SubPacketLen;
case GUILD_SUBHEADER_CG_CHANGE_MEMBER_GRADE:
{
const DWORD pid = *reinterpret_cast<const DWORD*>(c_pData);
const BYTE grade = *(c_pData + sizeof(DWORD));
const TGuildMember* m = pGuild->GetMember(ch->GetPlayerID());
if (NULL == m)
return -1;
if (m->grade != GUILD_LEADER_GRADE)
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xC1\xF7\xC0\xA7\xB8\xA6 \xBA\xAF\xB0\xE6\xC7\xD2 \xB1\xC7\xC7\xD1\xC0\xCC \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
else if (ch->GetPlayerID() == pid)
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB1\xE6\xB5\xE5\xC0\xE5\xC0\xC7 \xC1\xF7\xC0\xA7\xB4\xC2 \xBA\xAF\xB0\xE6\xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
else if (grade == 1)
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB1\xE6\xB5\xE5\xC0\xE5\xC0\xB8\xB7\xCE \xC1\xF7\xC0\xA7\xB8\xA6 \xBA\xAF\xB0\xE6\xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
else
pGuild->ChangeMemberGrade(pid, grade);
}
return SubPacketLen;
case GUILD_SUBHEADER_CG_USE_SKILL:
{
const TPacketCGGuildUseSkill* p = reinterpret_cast<const TPacketCGGuildUseSkill*>(c_pData);
pGuild->UseSkill(p->dwVnum, ch, p->dwPID);
}
return SubPacketLen;
case GUILD_SUBHEADER_CG_CHANGE_MEMBER_GENERAL:
{
const DWORD pid = *reinterpret_cast<const DWORD*>(c_pData);
const BYTE is_general = *(c_pData + sizeof(DWORD));
const TGuildMember* m = pGuild->GetMember(ch->GetPlayerID());
if (NULL == m)
return -1;
if (m->grade != GUILD_LEADER_GRADE)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xC0\xE5\xB1\xBA\xC0\xBB \xC1\xF6\xC1\xA4\xC7\xD2 \xB1\xC7\xC7\xD1\xC0\xCC \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
}
else
{
if (!pGuild->ChangeMemberGeneral(pid, is_general))
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<\xB1\xE6\xB5\xE5> \xB4\xF5\xC0\xCC\xBB\xF3 \xC0\xE5\xBC\xF6\xB8\xA6 \xC1\xF6\xC1\xA4\xC7\xD2 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
}
}
}
return SubPacketLen;
case GUILD_SUBHEADER_CG_GUILD_INVITE_ANSWER:
{
const DWORD guild_id = *reinterpret_cast<const DWORD*>(c_pData);
const BYTE accept = *(c_pData + sizeof(DWORD));
CGuild * g = CGuildManager::instance().FindGuild(guild_id);
if (g)
{
if (accept)
g->InviteAccept(ch);
else
g->InviteDeny(ch->GetPlayerID());
}
}
return SubPacketLen;
}
return 0;
}
void CInputMain::Fishing(LPCHARACTER ch, const char* c_pData)
{
TPacketCGFishing* p = (TPacketCGFishing*)c_pData;
ch->SetRotation(p->dir * 5);
ch->fishing();
return;
}
void CInputMain::ItemGive(LPCHARACTER ch, const char* c_pData)
{
TPacketCGGiveItem* p = (TPacketCGGiveItem*) c_pData;
LPCHARACTER to_ch = CHARACTER_MANAGER::instance().Find(p->dwTargetVID);
if (to_ch)
ch->GiveItem(to_ch, p->ItemPos);
else
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xBE\xC6\xC0\xCC\xC5\xDB\xC0\xBB \xB0\xC7\xB3\xD7\xC1\xD9 \xBC\xF6 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
}
int CInputMain::MyShop(LPCHARACTER ch, const char * c_pData, size_t uiBytes)
{
TPacketCGMyShop * p = (TPacketCGMyShop *) c_pData;
int iExtraLen = p->bCount * sizeof(TShopItemTable);
if (uiBytes < sizeof(TPacketCGMyShop) + iExtraLen)
return -1;
if (ch->GetGold() >= GOLD_MAX)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xBC\xD2\xC0\xAF \xB5\xB7\xC0\xCC 20\xBE\xEF\xB3\xC9\xC0\xBB \xB3\xD1\xBE\xEE \xB0\xC5\xB7\xA1\xB8\xA6 \xC7\xDB\xBC\xF6\xB0\xA1 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
SPDLOG_DEBUG("MyShop ==> OverFlow Gold id {} name {} ", ch->GetPlayerID(), ch->GetName());
return (iExtraLen);
}
if (ch->IsStun() || ch->IsDead())
return (iExtraLen);
if (ch->GetExchange() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->IsCubeOpen())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xB4\xD9\xB8\xA5 \xB0\xC5\xB7\xA1\xC1\xDF\xC0\xCF\xB0\xE6\xBF\xEC \xB0\xB3\xC0\xCE\xBB\xF3\xC1\xA1\xC0\xBB \xBF\xAD\xBC\xF6\xB0\xA1 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9."));
return (iExtraLen);
}
SPDLOG_DEBUG("MyShop count {}", p->bCount);
ch->OpenMyShop(p->szSign, (TShopItemTable *) (c_pData + sizeof(TPacketCGMyShop)), p->bCount);
return (iExtraLen);
}
void CInputMain::Refine(LPCHARACTER ch, const char* c_pData)
{
const TPacketCGRefine* p = reinterpret_cast<const TPacketCGRefine*>(c_pData);
if (ch->GetExchange() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->GetMyShop() || ch->IsCubeOpen())
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("\xC3\xA2\xB0\xED,\xB0\xC5\xB7\xA1\xC3\xA2\xB5\xEE\xC0\xCC \xBF\xAD\xB8\xB0 \xBB\xF3\xC5\xC2\xBF\xA1\xBC\xAD\xB4\xC2 \xB0\xB3\xB7\xAE\xC0\xBB \xC7\xD2\xBC\xF6\xB0\xA1 \xBE\xF8\xBD\xC0\xB4\xCF\xB4\xD9"));
ch->ClearRefineMode();
return;
}
if (p->type == 255)
{
// DoRefine Cancel
ch->ClearRefineMode();
return;
}
if (p->pos >= INVENTORY_MAX_NUM)
{
ch->ClearRefineMode();
return;
}
LPITEM item = ch->GetInventoryItem(p->pos);
if (!item)
{
ch->ClearRefineMode();
return;
}
ch->SetRefineTime();
if (p->type == REFINE_TYPE_NORMAL)
{
SPDLOG_DEBUG("refine_type_noraml");
ch->DoRefine(item);
}
else if (p->type == REFINE_TYPE_SCROLL || p->type == REFINE_TYPE_HYUNIRON || p->type == REFINE_TYPE_MUSIN || p->type == REFINE_TYPE_BDRAGON)
{
SPDLOG_DEBUG("refine_type_scroll, ...");
ch->DoRefineWithScroll(item);
}
else if (p->type == REFINE_TYPE_MONEY_ONLY)
{
const LPITEM item = ch->GetInventoryItem(p->pos);
if (NULL != item)
{
if (500 <= item->GetRefineSet())
{
LogManager::instance().HackLog("DEVIL_TOWER_REFINE_HACK", ch);
}
else
{
if (ch->GetQuestFlag("deviltower_zone.can_refine"))
{
ch->DoRefine(item, true);
ch->SetQuestFlag("deviltower_zone.can_refine", 0);
}
else
{
ch->ChatPacket(CHAT_TYPE_INFO, "\xBB\xE7\xB1\xCD \xC5\xB8\xBF\xF6 \xBF\xCF\xB7\xE1 \xBA\xB8\xBB\xF3\xC0\xBA \xC7\xD1\xB9\xF8\xB1\xEE\xC1\xF6 \xBB\xE7\xBF\xEB\xB0\xA1\xB4\xC9\xC7\xD5\xB4\xCF\xB4\xD9.");
}
}
}
}
ch->ClearRefineMode();
}
int CInputMain::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
{
LPCHARACTER ch;
if (!(ch = d->GetCharacter()))
{
SPDLOG_ERROR("no character on desc");
d->SetPhase(PHASE_CLOSE);
return (0);
}
int iExtraLen = 0;
if (test_server && bHeader != HEADER_CG_MOVE)
SPDLOG_TRACE("CInputMain::Analyze() ==> Header [{}] ", bHeader);
switch (bHeader)
{
case HEADER_CG_PONG:
Pong(d);
break;
case HEADER_CG_TIME_SYNC:
Handshake(d, c_pData);
break;
case HEADER_CG_CHAT:
if (test_server)
{
char* pBuf = (char*)c_pData;
SPDLOG_DEBUG("{}", pBuf + sizeof(TPacketCGChat));
}
if ((iExtraLen = Chat(ch, c_pData, m_iBufferLeft)) < 0)
return -1;
break;
case HEADER_CG_WHISPER:
if ((iExtraLen = Whisper(ch, c_pData, m_iBufferLeft)) < 0)
return -1;
break;
case HEADER_CG_MOVE:
Move(ch, c_pData);
if (LC_IsEurope())
{
if (g_bCheckClientVersion)
{
int version = atoi(g_stClientVersion.c_str());
int date = atoi(d->GetClientVersion());
//if (0 != g_stClientVersion.compare(d->GetClientVersion()))
if (version > date)
{
ch->ChatPacket(CHAT_TYPE_NOTICE, LC_TEXT("\xC5\xAC\xB6\xF3\xC0\xCC\xBE\xF0\xC6\xAE \xB9\xF6\xC0\xFC\xC0\xCC \xC6\xB2\xB7\xC1 \xB7\xCE\xB1\xD7\xBE\xC6\xBF\xF4 \xB5\xCB\xB4\xCF\xB4\xD9. \xC1\xA4\xBB\xF3\xC0\xFB\xC0\xB8\xB7\xCE \xC6\xD0\xC4\xA1 \xC8\xC4 \xC1\xA2\xBC\xD3\xC7\xCF\xBC\xBC\xBF\xE4."));
d->DelayedDisconnect(10);
LogManager::instance().HackLog("VERSION_CONFLICT", d->GetAccountTable().login, ch->GetName(), d->GetHostName());
}
}
}
else
{
if (!*d->GetClientVersion())
{
SPDLOG_ERROR("Version not recieved name {}", ch->GetName());
d->SetPhase(PHASE_CLOSE);
}
}
break;
case HEADER_CG_CHARACTER_POSITION:
Position(ch, c_pData);
break;
case HEADER_CG_ITEM_USE:
if (!ch->IsObserverMode())
ItemUse(ch, c_pData);
break;
case HEADER_CG_ITEM_DROP:
if (!ch->IsObserverMode())
{
ItemDrop(ch, c_pData);
}
break;
case HEADER_CG_ITEM_DROP2:
if (!ch->IsObserverMode())
ItemDrop2(ch, c_pData);
break;
case HEADER_CG_ITEM_MOVE:
if (!ch->IsObserverMode())
ItemMove(ch, c_pData);
break;
case HEADER_CG_ITEM_PICKUP:
if (!ch->IsObserverMode())
ItemPickup(ch, c_pData);
break;
case HEADER_CG_ITEM_USE_TO_ITEM:
if (!ch->IsObserverMode())
ItemToItem(ch, c_pData);
break;
case HEADER_CG_ITEM_GIVE:
if (!ch->IsObserverMode())
ItemGive(ch, c_pData);
break;
case HEADER_CG_EXCHANGE:
if (!ch->IsObserverMode())
Exchange(ch, c_pData);
break;
case HEADER_CG_ATTACK:
case HEADER_CG_SHOOT:
if (!ch->IsObserverMode())
{
Attack(ch, bHeader, c_pData);
}
break;
case HEADER_CG_USE_SKILL:
if (!ch->IsObserverMode())
UseSkill(ch, c_pData);
break;
case HEADER_CG_QUICKSLOT_ADD:
QuickslotAdd(ch, c_pData);
break;
case HEADER_CG_QUICKSLOT_DEL:
QuickslotDelete(ch, c_pData);
break;
case HEADER_CG_QUICKSLOT_SWAP:
QuickslotSwap(ch, c_pData);
break;
case HEADER_CG_SHOP:
if ((iExtraLen = Shop(ch, c_pData, m_iBufferLeft)) < 0)
return -1;
break;
case HEADER_CG_MESSENGER:
if ((iExtraLen = Messenger(ch, c_pData, m_iBufferLeft))<0)
return -1;
break;
case HEADER_CG_ON_CLICK:
OnClick(ch, c_pData);
break;
case HEADER_CG_SYNC_POSITION:
if ((iExtraLen = SyncPosition(ch, c_pData, m_iBufferLeft)) < 0)
return -1;
break;
case HEADER_CG_ADD_FLY_TARGETING:
case HEADER_CG_FLY_TARGETING:
FlyTarget(ch, c_pData, bHeader);
break;
case HEADER_CG_SCRIPT_BUTTON:
ScriptButton(ch, c_pData);
break;
// SCRIPT_SELECT_ITEM
case HEADER_CG_SCRIPT_SELECT_ITEM:
ScriptSelectItem(ch, c_pData);
break;
// END_OF_SCRIPT_SELECT_ITEM
case HEADER_CG_SCRIPT_ANSWER:
ScriptAnswer(ch, c_pData);
break;
case HEADER_CG_QUEST_INPUT_STRING:
QuestInputString(ch, c_pData);
break;
case HEADER_CG_QUEST_CONFIRM:
QuestConfirm(ch, c_pData);
break;
case HEADER_CG_TARGET:
Target(ch, c_pData);
break;
case HEADER_CG_WARP:
Warp(ch, c_pData);
break;
case HEADER_CG_SAFEBOX_CHECKIN:
SafeboxCheckin(ch, c_pData);
break;
case HEADER_CG_SAFEBOX_CHECKOUT:
SafeboxCheckout(ch, c_pData, false);
break;
case HEADER_CG_SAFEBOX_ITEM_MOVE:
SafeboxItemMove(ch, c_pData);
break;
case HEADER_CG_MALL_CHECKOUT:
SafeboxCheckout(ch, c_pData, true);
break;
case HEADER_CG_PARTY_INVITE:
PartyInvite(ch, c_pData);
break;
case HEADER_CG_PARTY_REMOVE:
PartyRemove(ch, c_pData);
break;
case HEADER_CG_PARTY_INVITE_ANSWER:
PartyInviteAnswer(ch, c_pData);
break;
case HEADER_CG_PARTY_SET_STATE:
PartySetState(ch, c_pData);
break;
case HEADER_CG_PARTY_USE_SKILL:
PartyUseSkill(ch, c_pData);
break;
case HEADER_CG_PARTY_PARAMETER:
PartyParameter(ch, c_pData);
break;
case HEADER_CG_ANSWER_MAKE_GUILD:
AnswerMakeGuild(ch, c_pData);
break;
case HEADER_CG_GUILD:
if ((iExtraLen = Guild(ch, c_pData, m_iBufferLeft)) < 0)
return -1;
break;
case HEADER_CG_FISHING:
Fishing(ch, c_pData);
break;
case HEADER_CG_MYSHOP:
if ((iExtraLen = MyShop(ch, c_pData, m_iBufferLeft)) < 0)
return -1;
break;
case HEADER_CG_REFINE:
Refine(ch, c_pData);
break;
case HEADER_CG_CLIENT_VERSION:
Version(ch, c_pData);
break;
case HEADER_CG_DRAGON_SOUL_REFINE:
{
TPacketCGDragonSoulRefine* p = reinterpret_cast <TPacketCGDragonSoulRefine*>((void*)c_pData);
switch(p->bSubType)
{
case DS_SUB_HEADER_CLOSE:
ch->DragonSoul_RefineWindow_Close();
break;
case DS_SUB_HEADER_DO_REFINE_GRADE:
{
DSManager::instance().DoRefineGrade(ch, p->ItemGrid);
}
break;
case DS_SUB_HEADER_DO_REFINE_STEP:
{
DSManager::instance().DoRefineStep(ch, p->ItemGrid);
}
break;
case DS_SUB_HEADER_DO_REFINE_STRENGTH:
{
DSManager::instance().DoRefineStrength(ch, p->ItemGrid);
}
break;
}
}
break;
}
return (iExtraLen);
}
int CInputDead::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
{
LPCHARACTER ch;
if (!(ch = d->GetCharacter()))
{
SPDLOG_ERROR("no character on desc");
return 0;
}
int iExtraLen = 0;
switch (bHeader)
{
case HEADER_CG_PONG:
Pong(d);
break;
case HEADER_CG_TIME_SYNC:
Handshake(d, c_pData);
break;
case HEADER_CG_CHAT:
if ((iExtraLen = Chat(ch, c_pData, m_iBufferLeft)) < 0)
return -1;
break;
case HEADER_CG_WHISPER:
if ((iExtraLen = Whisper(ch, c_pData, m_iBufferLeft)) < 0)
return -1;
break;
default:
return (0);
}
return (iExtraLen);
}