forked from metin2/server
3342 lines
94 KiB
C++
3342 lines
94 KiB
C++
#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);
|
||
}
|
||
|