#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 "HackShield.h" #include "XTrapManager.h" #include "DragonSoul.h" #ifdef ENABLE_SWITCHBOT #include "new_switchbot.h" #endif extern void SendShout(const char * szText, BYTE bEmpire); extern int g_nPortalLimitTime; static int __deposit_limit() { return (1000*10000); // 1õ¸¸ } #ifdef __ENABLE_SHOP_SEARCH_SYSTEM__ #include "entity.h" #include bool CompareItemVnumAcPriceAC(CShop::SHOP_ITEM i, CShop::SHOP_ITEM j) { return (i.vnum < j.vnum) && (i.price < j.price); } #include "entity.h" void CInputMain::ShopSearch(LPCHARACTER ch, const char * data, bool bName) { TPacketCGShopSearch * pinfo = (TPacketCGShopSearch *)data; if (!ch) return; if (!data) return; if (ch->IsOpenSafebox() || ch->GetShop() || ch->IsCubeOpen() || ch->IsDead() || ch->GetExchange() || ch->GetMyShop()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("CANT_DO_THIS_BECAUSE_OTHER_WINDOW_OPEN")); return; } if (0 == quest::CQuestManager::instance().GetEventFlag("enable_shop_search")) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("PRIVATE_SHOP_SEARCH_SYSTEM_DISABLED")); return; } #ifndef DISABLE_PRIVATE_SHOP_SEARCH_NEED_ITEM if (!ch->FindSpecifyItem(60004) && !ch->FindSpecifyItem(60005) && !ch->FindSpecifyItem(87009)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("PRIVATE_SHOP_SEARCH_NEED_ITEM")); return; } #endif int32_t Race = pinfo->Race; int32_t Cat = pinfo->ItemCat; int32_t SubCat = pinfo->SubCat; int32_t MinLevel = pinfo->MinLevel; int32_t MaxLevel = pinfo->MaxLevel; int32_t MinRefine = pinfo->MinRefine; int32_t MaxRefine = pinfo->MaxRefine; uint64_t MinGold = pinfo->MinGold; uint64_t MaxGold = pinfo->MaxGold; std::string itemName = ""; //Checks if (Race < JOB_WARRIOR || Race > JOB_SURA) return; if (Cat < ITEM_NONE || Cat > ITEM_BELT) return; if (SubCat < USE_POTION || SubCat > USE_PUT_INTO_ACCESSORY_SOCKET) return; if (MinLevel < 0 || MinLevel > PLAYER_MAX_LEVEL_CONST) return; if (MaxLevel < 0 || MaxLevel > PLAYER_MAX_LEVEL_CONST) return; if (MinRefine < 0 || MinRefine > 9) return; if (MaxRefine < 0 || MaxRefine > 9) return; if (MinGold < 0 || MinGold > GOLD_MAX) return; if (MaxGold < 0 || MaxGold > GOLD_MAX) return; if (MinLevel > MaxLevel) return; if (MinRefine > MaxRefine) return; if (MinGold > MaxGold) return; if (bName) { itemName = pinfo->ItemName; std::replace(itemName.begin(), itemName.end(), '_', ' '); } quest::PC* pPC = quest::CQuestManager::instance().GetPC(ch->GetPlayerID()); if (!pPC) return; DWORD dwShopSearchSecCycle = 2; // 1 sec DWORD dwNowSec = get_global_time(); DWORD dwLastShopSearchAttrSec = pPC->GetFlag("ShopSearch.LastShopSearchSecAttr"); if (dwLastShopSearchAttrSec + dwShopSearchSecCycle > dwNowSec) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("PRIVATE_SHOP_SEARCH_NEED_WAIT_%d_LEFT_(%d)"), dwShopSearchSecCycle, dwShopSearchSecCycle - (dwNowSec - dwLastShopSearchAttrSec)); return; } pPC->SetFlag("ShopSearch.LastShopSearchSecAttr", dwNowSec); if (bName) sys_log(0, "SHOP_SEARCH: CharName: %s Search: Race: %d Cat: %d SubCat: %d MinLevel: %d MaxLevel: %d MinRefine: %d MaxRefine: %d MinGold: %llu MaxGold: %llu itemName: %s", ch->GetName(), Race, Cat, SubCat, MinLevel, MaxLevel, MinRefine, MaxRefine, MinGold, MaxGold, itemName.c_str()); else sys_log(0, "SHOP_SEARCH: CharName: %s Search: Race: %d Cat: %d SubCat: %d MinLevel: %d MaxLevel: %d MinRefine: %d MaxRefine: %d MinGold: %llu MaxGold: %llu", ch->GetName(), Race, Cat, SubCat, MinLevel, MaxLevel, MinRefine, MaxRefine, MinGold, MaxGold); CEntity::ENTITY_MAP viewmap = ch->GetViewMap(); CEntity::ENTITY_MAP::iterator it = viewmap.begin(); std::vector sendItems; while (it != viewmap.end()) { if (it->first->GetType() != ENTITY_CHARACTER) { ++it; continue; } LPCHARACTER tch = static_cast((it++)->first); if (!tch) continue; if (!tch->GetMyShop() || tch == ch) continue; std::vector shop_items = tch->GetMyShop()->GetItemVector(); std::vector::iterator item; for (item = shop_items.begin(); item != shop_items.end(); ++item) { if (bName) { LPITEM curItem = item->pkItem; if (!curItem) continue; if (curItem && itemName.length() > 2) { if (!((curItem->GetLevelLimit() >= MinLevel && curItem->GetLevelLimit() <= MaxLevel) || curItem->GetLevelLimit() == 0)) continue; if (!(item->price >= MinGold && item->price <= MaxGold)) continue; bool pushback = false; std::string foundName = curItem->GetName(); if (foundName.find(itemName) != std::string::npos) { pushback = true; } if (pushback) { sendItems.push_back(*item); } } } else { LPITEM curItem = item->pkItem; if (!curItem) continue; if (curItem && curItem->GetType() == Cat && curItem->GetSubType() == SubCat) { if ((curItem->GetType() == ITEM_WEAPON || curItem->GetType() == ITEM_ARMOR) && !(curItem->GetRefineLevel() >= MinRefine && curItem->GetRefineLevel() <= MaxRefine)) continue; if (!((curItem->GetLevelLimit() >= MinLevel && curItem->GetLevelLimit() <= MaxLevel) || curItem->GetLevelLimit() == 0)) continue; if (!(item->price >= MinGold && item->price <= MaxGold)) continue; bool cont = false; switch (Race) { case JOB_WARRIOR: if (curItem->GetAntiFlag() & ITEM_ANTIFLAG_WARRIOR) cont = true; break; case JOB_ASSASSIN: if (curItem->GetAntiFlag() & ITEM_ANTIFLAG_ASSASSIN) cont = true; break; case JOB_SHAMAN: if (curItem->GetAntiFlag() & ITEM_ANTIFLAG_SHAMAN) cont = true; break; case JOB_SURA: if (curItem->GetAntiFlag() & ITEM_ANTIFLAG_SURA) cont = true; break; } if (cont) continue; sendItems.push_back(*item); } } } } std::stable_sort(sendItems.begin(), sendItems.end(), CompareItemVnumAcPriceAC); std::vector::iterator item; for (item = sendItems.begin(); item != sendItems.end(); ++item) { LPITEM curItem = item->pkItem; if (curItem) { LPDESC d = ch->GetDesc(); if (!d) return; TPacketGCShopSearchItemSet pack; pack.header = HEADER_GC_SHOPSEARCH_SET; pack.count = static_cast(item->count); pack.vnum = curItem->GetVnum(); pack.flags = curItem->GetFlag(); pack.anti_flags = curItem->GetAntiFlag(); pack.price = item->price; pack.vid = curItem->GetOwner()->GetVID(); pack.Cell = item->pos; thecore_memcpy(pack.alSockets, curItem->GetSockets(), sizeof(pack.alSockets)); thecore_memcpy(pack.aAttr, curItem->GetAttributes(), sizeof(pack.aAttr)); d->LargePacket(&pack, sizeof(TPacketGCShopSearchItemSet)); } } } void CInputMain::ShopSearchBuy(LPCHARACTER ch, const char * data) { TPacketCGShopSearchBuy * pinfo = (TPacketCGShopSearchBuy *)data; int32_t shopVid = pinfo->shopVid; int32_t shopItemPos = pinfo->shopItemPos; if (!ch) return; if (0 == quest::CQuestManager::instance().GetEventFlag("enable_shop_search")) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("PRIVATE_SHOP_SEARCH_SYSTEM_DISABLED")); return; } if (ch->IsOpenSafebox() || ch->GetShop() || ch->IsCubeOpen() || ch->IsDead() || ch->GetExchange() || ch->GetMyShop()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("CANT_DO_THIS_BECAUSE_OTHER_WINDOW_OPEN")); return; } #ifndef DISABLE_PRIVATE_SHOP_SEARCH_NEED_ITEM if (!ch->FindSpecifyItem(60005) && !ch->FindSpecifyItem(60006) && !ch->FindSpecifyItem(87009)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("PRIVATE_SHOP_SEARCH_NEED_ITEM")); return; } #endif LPCHARACTER pkChrShop = CHARACTER_MANAGER::instance().Find(shopVid); if (!pkChrShop) return; LPSHOP pkShop = pkChrShop->GetMyShop(); if (!pkShop) return; if (pkShop->IsLocked()) { sys_err("Player %lu trying to buy from closed shop.", ch->GetPlayerID()); return; } if (DISTANCE_APPROX(ch->GetX() - pkChrShop->GetX(), ch->GetY() - pkChrShop->GetY()) > VIEW_RANGE) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("???? ??? ?? ?? ??? ? ? ????.")); return; } if (ch->GetMapIndex() != pkChrShop->GetMapIndex()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("YOU_CANNOT_BUY_THIS_BECAUSE_NOT_IN_SAME_MAP")); return; } int32_t returnHeader = pkShop->Buy(ch, shopItemPos, false); if (SHOP_SUBHEADER_GC_OK == returnHeader) { // being lazy starting in 3 2 .. ch->ChatPacket(CHAT_TYPE_COMMAND, "ShopSearchBuy"); } else { ch->ChatPacket(CHAT_TYPE_COMMAND, "ShopSearchError %d", returnHeader); } //If, after buying, the shop is closed, destroy it (through its owner char) /*if (pkShop->IsClosed() && pkShop->IsPCShop()) { M2_DESTROY_CHARACTER(pkShop->GetOwner()); }*/ } #endif void SendBlockChatInfo(LPCHARACTER ch, int sec) { if (sec <= 0) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("äÆà ±İÁö »óÅÂÀÔ´Ï´Ù.")); return; } long hour = sec / 3600; sec -= hour * 3600; long min = (sec / 60); sec -= min * 60; char buf[128+1]; if (hour > 0 && min > 0) snprintf(buf, sizeof(buf), LC_TEXT("%d ½Ã°£ %d ºĞ %d ÃÊ µ¿¾È äÆñİÁö »óÅÂÀÔ´Ï´Ù"), hour, min, sec); else if (hour > 0 && min == 0) snprintf(buf, sizeof(buf), LC_TEXT("%d ½Ã°£ %d ÃÊ µ¿¾È äÆñİÁö »óÅÂÀÔ´Ï´Ù"), hour, sec); else if (hour == 0 && min > 0) snprintf(buf, sizeof(buf), LC_TEXT("%d ºĞ %d ÃÊ µ¿¾È äÆñİÁö »óÅÂÀÔ´Ï´Ù"), min, sec); else snprintf(buf, sizeof(buf), LC_TEXT("%d ÃÊ µ¿¾È äÆñİÁö »óÅÂÀÔ´Ï´Ù"), 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 boost::unordered_map > 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( event->info ); if ( info == NULL ) { sys_err( "block_chat_by_ip_event> 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) sys_log(0, "SPAM_SCORE: %s text: %s score: %u total: %u word: %s", 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(); 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)); sys_log(0, "SPAM_IP: %s for %u 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) { return 0; // Disable Glass //°³ÀλóÁ¡Áß¿¡ ±İ°­°æÀ» »ç¿ëÇÒ °æ¿ì //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()) { return 3; } int nPrismCount; if (!g_bDisablePrismNeed) { nPrismCount = ch->CountSpecifyItem(ITEM_PRISM); if (nPrismCount < hyperlinks) return 0; } if (!ch->GetMyShop()) { if(!g_bDisablePrismNeed) ch->RemoveSpecifyItem(ITEM_PRISM, hyperlinks); return 0; } else { if (!g_bDisablePrismNeed) { 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(data); if (uiBytes < pinfo->wSize) return -1; int iExtraLen = pinfo->wSize - sizeof(TPacketCGWhisper); if (iExtraLen < 0) { sys_err("invalid packet length (len %d size %u buffer %u)", iExtraLen, pinfo->wSize, uiBytes); ch->GetDesc()->SetPhase(PHASE_CLOSE); return -1; } if (ch->FindAffect(AFFECT_BLOCK_CHAT)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("äÆà ±İÁö »óÅÂÀÔ´Ï´Ù.")); 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) sys_log(0, "Whisper to %s(%s) from %s", "Null", pinfo->szNameTo, ch->GetName()); else sys_log(0, "Whisper to %s(%s) from %s", 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; if (test_server) sys_log(0, "Whisper to %s from %s (Channel %d Mapindex %d)", "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)); sys_log(0, "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), MIN(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("»ç¿ëÇÒ¼ö ¾ø½À´Ï´Ù."), pTable->szLocaleName); else len = snprintf(buf, sizeof(buf), LC_TEXT("%sÀÌ ÇÊ¿äÇÕ´Ï´Ù."), 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()->BufferedPacket(&pack, sizeof(pack)); ch->GetDesc()->Packet(buf, len); sys_log(0, "WHISPER: not enough %s: char: %s", 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) { sys_log(0, "WHISPER: %s -> %s : %s", 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->BufferedPacket(&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 { // »ç¶÷¸¶´Ù ½ºÅ³·¹º§ÀÌ ´Ù¸£´Ï ¸Å¹ø ÇؾßÇÕ´Ï´Ù size_t len = strlcpy(converted_msg, orig_msg, sizeof(converted_msg)); if (len >= sizeof(converted_msg)) len = sizeof(converted_msg) - 1; ConvertEmpireText(bEmpire, converted_msg + namelen, len - 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->BufferedPacket(&packet, sizeof(packet_chat)); d->Packet(m_orig_msg, m_len_orig_msg); } else { packet.size = m_len_conv_msg + sizeof(TPacketGCChat); d->BufferedPacket(&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(data); if (uiBytes < pinfo->size) return -1; const int iExtraLen = pinfo->size - sizeof(TPacketCGChat); if (iExtraLen < 0) { sys_err("invalid packet length (len %d size %u buffer %u)", 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), MIN(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) { sys_log(0, "CHAT_HACK: %s", 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; if (g_bShoutAddonEnable) { len = snprintf(chatbuf, sizeof(chatbuf), "[%s]%s : %s", LC_TEXT(c_apszEmpireNames[ch->GetEmpire()]), ch->GetName(), buf); } else { 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("»ç¿ëÇÒ¼ö ¾ø½À´Ï´Ù."), pTable->szLocaleName); else ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%sÀÌ ÇÊ¿äÇÕ´Ï´Ù."), pTable->szLocaleName); } return iExtraLen; } if (pinfo->type == CHAT_TYPE_SHOUT) { const int SHOUT_LIMIT_LEVEL = 15; if (ch->GetLevel() < SHOUT_LIMIT_LEVEL) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¿ÜÄ¡±â´Â ·¹º§ %d ÀÌ»ó¸¸ »ç¿ë °¡´É ÇÕ´Ï´Ù."), 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("ÆÄƼ ÁßÀÌ ¾Æ´Õ´Ï´Ù.")); 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("±æµå¿¡ °¡ÀÔÇÏÁö ¾Ê¾Ò½À´Ï´Ù.")); else ch->GetGuild()->Chat(chatbuf); } break; default: sys_err("Unknown chat type %d", 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; #ifdef ENABLE_CHEQUE_SYSTEM if (pinfo->gold >0 && pinfo->cheque >0) ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't do it.")); else if (pinfo->cheque > 0) ch->DropCheque(pinfo->cheque); else if (pinfo->gold > 0) ch->DropGold(pinfo->gold); else ch->DropItem(pinfo->Cell); #else if (pinfo->gold > 0) ch->DropGold(pinfo->gold); else ch->DropItem(pinfo->Cell); #endif } 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; #ifdef ENABLE_CHEQUE_SYSTEM if (pinfo->gold >0 && pinfo->cheque >0) ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't do it.")); else if (pinfo->cheque > 0) ch->DropCheque(pinfo->cheque); else if (pinfo->gold > 0) ch->DropGold(pinfo->gold); else ch->DropItem(pinfo->Cell); #else if (pinfo->gold > 0) ch->DropGold(pinfo->gold); else ch->DropItem(pinfo->Cell, pinfo->count); #endif } #ifdef __NEW_DROP_DIALOG__ void CInputMain::ItemDestroy(LPCHARACTER ch, const char* data) { struct command_item_destroy* pinfo = (struct command_item_destroy*) data; if (ch) ch->DestroyItem(pinfo->Cell); } #endif 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::QuickslotAdd(LPCHARACTER ch, const char * data) { struct command_quickslot_add * pinfo = (struct command_quickslot_add *) data; if(pinfo->slot.type == QUICKSLOT_TYPE_ITEM) { LPITEM item = NULL; TItemPos srcCell(INVENTORY, pinfo->slot.pos); if (!(item = ch->GetItem(srcCell))) return; if (item->GetType() != ITEM_USE && item->GetType() != ITEM_QUEST) return; } 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("»ó´ë¹æÀÌ ¸Ş½ÅÁ® Ãß°¡ °ÅºÎ »óÅÂÀÔ´Ï´Ù.")); 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("<¸Ş½ÅÁ®> ¿î¿µÀÚ´Â ¸Ş½ÅÁ®¿¡ Ãß°¡ÇÒ ¼ö ¾ø½À´Ï´Ù.")); 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("<¸Ş½ÅÁ®> ¿î¿µÀÚ´Â ¸Ş½ÅÁ®¿¡ Ãß°¡ÇÒ ¼ö ¾ø½À´Ï´Ù.")); return CHARACTER_NAME_MAX_LEN; } LPCHARACTER tch = CHARACTER_MANAGER::instance().FindPC(name); if (!tch) ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s ´ÔÀº Á¢¼ÓµÇ ÀÖÁö ¾Ê½À´Ï´Ù."), name); else { if (tch == ch) // ÀÚ½ÅÀº Ãß°¡ÇÒ ¼ö ¾ø´Ù. return CHARACTER_NAME_MAX_LEN; if (tch->IsBlockMode(BLOCK_MESSENGER_INVITE) == true) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ó´ë¹æÀÌ ¸Ş½ÅÁ® Ãß°¡ °ÅºÎ »óÅÂÀÔ´Ï´Ù.")); } 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: sys_err("CInputMain::Messenger : Unknown subheader %d : %s", 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; if (test_server) sys_log(0, "CInputMain::Shop() ==> SubHeader %d", p->subheader); const char * c_pData = data + sizeof(TPacketCGShop); uiBytes -= sizeof(TPacketCGShop); switch (p->subheader) { case SHOP_SUBHEADER_CG_END: sys_log(1, "INPUT: %s 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); sys_log(1, "INPUT: %s SHOP: BUY %d", 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; sys_log(0, "INPUT: %s 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); sys_log(0, "INPUT: %s SHOP: SELL2", ch->GetName()); CShopManager::instance().Sell(ch, pos, count); return sizeof(BYTE) + sizeof(BYTE); } default: sys_err("CInputMain::Shop : Unknown subheader %d : %s", 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 if (test_server) { sys_err("CInputMain::OnClick %s.Click.NOT_EXIST_VID[%d]", 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("°Å·¡ ÈÄ %dÃÊ À̳»¿¡ â°í¸¦ ¿­¼ö ¾ø½À´Ï´Ù."), g_nPortalLimitTime); return; } if( true == to_ch->IsDead() ) { return; } } sys_log(0, "CInputMain()::Exchange() SubHeader %d ", pinfo->sub_header); if (iPulse - ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°Å·¡ ÈÄ %dÃÊ À̳»¿¡ â°í¸¦ ¿­¼ö ¾ø½À´Ï´Ù."), 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("±ºÁÖ¿Í´Â °Å·¡¸¦ ÇÒ¼ö°¡ ¾ø½À´Ï´Ù"), g_nPortalLimitTime); return; } //END_MONARCH_LIMIT */ if (iPulse - ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("â°í¸¦ ¿¬ÈÄ %dÃÊ À̳»¿¡´Â °Å·¡¸¦ ÇÒ¼ö ¾ø½À´Ï´Ù."), 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("â°í¸¦ ¿¬ÈÄ %dÃÊ À̳»¿¡´Â °Å·¡¸¦ ÇÒ¼ö ¾ø½À´Ï´Ù."), 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("¾×¼ö°¡ 20¾ï ³ÉÀ» ÃÊ°úÇÏ¿© °Å·¡¸¦ ÇÒ¼ö°¡ ¾ø½À´Ï´Ù..")); sys_err("[OVERFLOG_GOLD] START (%u) id %u name %s ", ch->GetGold(), ch->GetPlayerID(), ch->GetName()); return; } if (to_ch->IsPC()) { if (quest::CQuestManager::instance().GiveItemToPC(ch->GetPlayerID(), to_ch)) { sys_log(0, "Exchange canceled by quest %s %s", ch->GetName(), to_ch->GetName()); return; } } if (ch->GetMyShop() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->IsCubeOpen()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´Ù¸¥ °Å·¡ÁßÀÏ°æ¿ì °³ÀλóÁ¡À» ¿­¼ö°¡ ¾ø½À´Ï´Ù.")); 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(ch->GetExchange()->GetCompany()->GetOwner()->GetGold()) + static_cast(pinfo->arg1); if (GOLD_MAX <= nTotalGold) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ó´ë¹æÀÇ Ãѱݾ×ÀÌ 20¾ï ³ÉÀ» ÃÊ°úÇÏ¿© °Å·¡¸¦ ÇÒ¼ö°¡ ¾ø½À´Ï´Ù..")); sys_err("[OVERFLOW_GOLD] ELK_ADD (%u) id %u name %s ", 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; #ifdef ENABLE_CHEQUE_SYSTEM case EXCHANGE_SUBHEADER_CG_CHEQUE_ADD: // arg1 == amount of cheque if (ch->GetExchange()) { const int64_t nTotalCheque = static_cast(ch->GetExchange()->GetCompany()->GetOwner()->GetCheque()) + static_cast(pinfo->arg1); if (CHEQUE_MAX <= nTotalCheque) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("You can't trade because the other character exceeds 999 won.")); sys_err("[OVERFLOW_CHEQUE] CHEQUE_ADD (%u) id %u name %s ", ch->GetExchange()->GetCompany()->GetOwner()->GetCheque(), ch->GetExchange()->GetCompany()->GetOwner()->GetPlayerID(), ch->GetExchange()->GetCompany()->GetOwner()->GetName()); return; } if (ch->GetExchange()->GetCompany()->GetAcceptStatus() != true) ch->GetExchange()->AddCheque(pinfo->arg1); } break; #endif case EXCHANGE_SUBHEADER_CG_ACCEPT: // arg1 == not used if (ch->GetExchange()) { sys_log(0, "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 bool CheckComboHack(LPCHARACTER ch, BYTE bArg, DWORD dwTime, bool CheckSpeedHack) { if(!gHackCheckEnable) return false; // Áװųª ±âÀı »óÅ¿¡¼­´Â °ø°İÇÒ ¼ö ¾øÀ¸¹Ç·Î, 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 #if 0 sys_log(0, "COMBO: %s arg:%u seq:%u delta:%d checkspeedhack:%d", 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; //sys_log(0, "COMBO_HACK: 2 %s arg:%u interval:%d valid:%u atkspd:%u riding:%s", // ch->GetName(), // bArg, // ComboInterval, // ch->GetValidComboInterval(), // ch->GetPoint(POINT_ATT_SPEED), // ch->IsRiding() ? "yes" : "no"); } ch->SetComboSequence(1); ch->SetValidComboInterval((int) (ani_combo_speed(ch, 1) / (ch->GetPoint(POINT_ATT_SPEED) / 100.f))); ch->SetLastComboTime(dwTime); } else if (bArg > 14 && bArg < 22) { int idx = MIN(2, ch->GetComboIndex()); if (ch->GetComboSequence() > 5) // ÇöÀç 6ÄŞº¸ ÀÌ»óÀº ¾ø´Ù. { HackScalar = 1; ch->SetValidComboInterval(300); sys_log(0, "COMBO_HACK: 5 %s combo_seq:%d", 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); sys_log(0, "COMBO_HACK: 3 %s arg:%u valid:%u combo_idx:%d combo_seq:%d", 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; sys_log(0, "COMBO_HACK: 2 %s arg:%u interval:%d valid:%u atkspd:%u riding:%s", 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); ch->SetValidComboInterval((int) (ani_combo_speed(ch, bArg - 13) / (ch->GetPoint(POINT_ATT_SPEED) / 100.f))); 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; //sys_log(0, "COMBO_HACK: 6 %s arg:%u interval:%d valid:%u atkspd:%u", // 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) sys_err("cannot find motion by race %u", 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); } */ 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->SetLastComboTime(dwTime); // END_OF_POLYMORPH_BUG_FIX } else { // ¸»ÀÌ ¾ÈµÇ´Â ÄŞº¸°¡ ¿Ô´Ù ÇØÄ¿ÀÏ °¡´É¼º? //if (ch->GetDesc()->DelayedDisconnect(number(2, 9))) //{ // LogManager::instance().HackLog("Hacker", ch); // sys_log(0, "HACKER: %s arg %u", ch->GetName(), bArg); //} // À§ ÄÚµå·Î ÀÎÇØ, Æú¸®¸ğÇÁ¸¦ Ǫ´Â Áß¿¡ °ø°İ Çϸé, // °¡²û ÇÙÀ¸·Î ÀνÄÇÏ´Â °æ¿ì°¡ ÀÖ´Ù. // ÀÚ¼¼È÷ ¸»Çô¸é, // ¼­¹ö¿¡¼­ poly 0¸¦ ó¸®ÇßÁö¸¸, // Ŭ¶ó¿¡¼­ ±× ÆĞŶÀ» ¹Ş±â Àü¿¡, ¸÷À» °ø°İ. <- Áï, ¸÷ÀÎ »óÅ¿¡¼­ °ø°İ. // // ±×·¯¸é Ŭ¶ó¿¡¼­´Â ¼­¹ö¿¡ ¸÷ »óÅ·Π°ø°İÇß´Ù´Â Ä¿¸Çµå¸¦ º¸³»°í (arg == 13) // // ¼­¹ö¿¡¼­´Â race´Â Àΰ£Àε¥ °ø°İÇüÅ´ ¸÷ÀÎ ³ğÀÌ´Ù! ¶ó°í ÇÏ¿© ÇÙüũ¸¦ Çß´Ù. // »ç½Ç °ø°İ ÆĞÅÏ¿¡ ´ëÇÑ °ÍÀº Ŭ¶óÀ̾ğÆ®¿¡¼­ ÆÇ´ÜÇؼ­ º¸³¾ °ÍÀÌ ¾Æ´Ï¶ó, // ¼­¹ö¿¡¼­ ÆÇ´ÜÇØ¾ß ÇÒ °ÍÀε¥... ¿Ö ÀÌ·¸°Ô ÇسùÀ»±î... // by rtsummit } } else { // ¸»ÀÌ ¾ÈµÇ´Â ÄŞº¸°¡ ¿Ô´Ù ÇØÄ¿ÀÏ °¡´É¼º? if (ch->GetDesc()->DelayedDisconnect(number(2, 9))) { LogManager::instance().HackLog("Hacker", ch); sys_log(0, "HACKER: %s arg %u", 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)) { sys_err("invalid move type: %s", 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) { 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); // ºÎÁ¤È®ÇÒ ¼ö ÀÖÀ½ } sys_log(0, "MOVE: %s trying to move too far (dist: %.1fm) Riding(%d)", 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) { sys_log(0, "SPEEDHACK: slow timer name %s delta %d", ch->GetName(), iDelta); ch->GetDesc()->DelayedDisconnect(3); } // 1ÃÊ¿¡ 20msec »¡¸® °¡´Â°Å ±îÁö´Â ÀÌÇØÇÑ´Ù. else if (iDelta < -(iServerDelta / 50)) { sys_log(0, "SPEEDHACK: DETECTED! %s (delta %d %d)", 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()); sys_log(0, "%s", szBuf); if (test_server) { ch->GetDesc()->DelayedDisconnect(number(2, 8)); ch->ChatPacket(CHAT_TYPE_INFO, szBuf); } else { ch->GetDesc()->DelayedDisconnect(number(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(number(15, 30))) LogManager::instance().HackLog("Debugger", ch); } else if (pinfo->dwTime == 10653971) // Softice ¹ß°ß { if (ch->GetDesc()->DelayedDisconnect(number(15, 30))) LogManager::instance().HackLog("Softice", ch); } */ /* sys_log(0, "MOVE: %s Func:%u Arg:%u Pos:%dx%d Time:%u 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(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(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(data); ch->Shoot(packShoot->bType); } break; } } int CInputMain::SyncPosition(LPCHARACTER ch, const char * c_pcData, size_t uiBytes) { const TPacketCGSyncPosition* pinfo = reinterpret_cast( c_pcData ); if (uiBytes < pinfo->wSize) return -1; int iExtraLen = pinfo->wSize - sizeof(TPacketCGSyncPosition); if (iExtraLen < 0) { sys_err("invalid packet length (len %d size %u buffer %u)", iExtraLen, pinfo->wSize, uiBytes); ch->GetDesc()->SetPhase(PHASE_CLOSE); return -1; } if (0 != (iExtraLen % sizeof(TPacketCGSyncPositionElement))) { sys_err("invalid packet length %d (name: %s)", 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 ); sys_err( "Too many SyncPosition Count(%d) from Name(%s)", 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(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 ); sys_err( "Too far SyncPosition DistanceWithSyncOwner(%f)(%s) from Name(%s) CH(%d,%d) VICTIM(%d,%d) SYNC(%d,%d)", 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 long g_lValidSyncInterval = 100 * 1000; // 100ms 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 ); sys_err( "Too often SyncPosition Interval(%ldms)(%s) from Name(%s) VICTIM(%d,%d) SYNC(%d,%d)", 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 ); sys_err( "Too far SyncPosition Distance(%f)(%s) from Name(%s) CH(%d,%d) VICTIM(%d,%d) SYNC(%d,%d)", 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; sys_log(0, "QUEST ScriptButton pid %d idx %u", 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) { //Äù½ºÆ® â¿¡¼­ Ŭ¸¯½Ã(__SelectQuest) ¿©±â·Î quest::CQuestManager::Instance().QuestInfo(ch->GetPlayerID(), p->idx & 0x7fffffff); } else { quest::CQuestManager::Instance().QuestButton(ch->GetPlayerID(), p->idx); } } #ifdef OFFLINE_MESSAGE void CInputMain::OfflineWhisper(LPCHARACTER ch, const char* data) { TPacketCGOfflineMessage * p = (TPacketCGOfflineMessage *)data; if (!ch) return; if (!p->szTargetName){ ch->ChatPacket(CHAT_TYPE_INFO, "Bad format - 0x01"); sys_err("Hedef ismi tanimlanmamis. From: %u", ch->GetPlayerID()); return; } if (!p->szText){ ch->ChatPacket(CHAT_TYPE_INFO, "Bad format - 0x02"); sys_err("Mesaj tanimlanamadi. From: %u", ch->GetPlayerID()); return; } if (strlen(p->szTargetName) < 2){ ch->ChatPacket(CHAT_TYPE_INFO, "Bad format - 0x03"); sys_err("Cevrimdisi mesaj paketinde hedef ismi cok kisa. Kim: %u", ch->GetPlayerID()); return; } if (strstr(p->szTargetName, "DROP") || strstr(p->szTargetName, "TRUNCATE") || strstr(p->szText, "DROP") || strstr(p->szText, "TRUNCATE")){ sys_err("HACKER: %s Name: %s Text: %s", ch->GetName(), p->szTargetName, p->szText); return; } int GetLastMsgTime = ch->GetQuestFlag("offline_msg.flood_check"); if (GetLastMsgTime) { if (get_global_time() < GetLastMsgTime + 15 /* limit */) { ch->ChatPacket(CHAT_TYPE_INFO, "Bunu bu kadar hizli yapamazsin."); return; } } char szEscapedTargetName[CHARACTER_NAME_MAX_LEN * 2 + 1]; DBManager::instance().EscapeString(szEscapedTargetName, sizeof(szEscapedTargetName), p->szTargetName, strlen(p->szTargetName)); char szEscapedMessage[CHAT_MAX_LEN * 2 + 1]; DBManager::instance().EscapeString(szEscapedMessage, sizeof(szEscapedMessage), p->szText, strlen(p->szText)); LPCHARACTER pTarget = CHARACTER_MANAGER::instance().FindPC(szEscapedTargetName); if (pTarget){ if (pTarget->GetDesc()){ ch->ChatPacket(CHAT_TYPE_INFO, "%s zaten cevrimici.", szEscapedTargetName); sys_err("Cevrimdisi mesaj gonderilemedi, oyuncu zaten cevrimici. Sahip: %s Su kisiye: %s", ch->GetName(), szEscapedTargetName); return; } } if (!strcmp(szEscapedTargetName, ch->GetName())){ ch->ChatPacket(CHAT_TYPE_INFO, "Kendine cevrimdisi mesaj gonderemezsin."); return; } std::auto_ptr pOwnerQuery(DBManager::instance().DirectQuery("SELECT id FROM player.player WHERE name = '%s'", szEscapedTargetName)); if (pOwnerQuery->uiSQLErrno != 0) { ch->ChatPacket(CHAT_TYPE_INFO, "Cevrimdisi mesaj gonderilemedi, bilinmeyen hata."); sys_err("Cevrimdisi Mesaj sorgusu basarisiz, Hata kodu: %ld", pOwnerQuery->uiSQLErrno); return; } if (!pOwnerQuery->Get()->uiNumRows){ ch->ChatPacket(CHAT_TYPE_INFO, "Boyle bir kullanici ismi sistemde mevcut degil. Mesajiniz iptal edildi."); sys_err("Mesaj sorgusu basarisiz, satirlar alinamadi. Hedef kullanici bulunamadi."); return; } MYSQL_ROW row = mysql_fetch_row(pOwnerQuery->Get()->pSQLResult); const char * cTargetPID = row[0]; DWORD dwTargetPID = 0; str_to_number(dwTargetPID, cTargetPID); sys_log(0, "Cevrimdisi mesaj gonderildi, Sahip: [%u]%s Su kisiye: [%u]%s Msg: %s", ch->GetPlayerID(), ch->GetName(), dwTargetPID, szEscapedTargetName, szEscapedMessage); char szOffMsgFormatted[CHAT_MAX_LEN * 2]; sprintf(szOffMsgFormatted, "%s_%d_%s", ch->GetName(), get_global_time(), szEscapedMessage); ch->SaveOfflineMessage(szOffMsgFormatted, dwTargetPID); ch->SetQuestFlag("offline_msg.flood_check", get_global_time()); if (test_server) sys_err("Offline message saved. To: %u Msg: %s", dwTargetPID, szOffMsgFormatted); } #endif void CInputMain::ScriptAnswer(LPCHARACTER ch, const void* c_pData) { TPacketCGScriptAnswer * p = (TPacketCGScriptAnswer *) c_pData; sys_log(0, "QUEST ScriptAnswer pid %d answer %d", 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; sys_log(0, "QUEST ScriptSelectItem pid %d answer %d", 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)); sys_log(0, "QUEST InputString pid %u msg %s", 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; sys_log(0, "QuestConfirm from %s pid %u name %s answer %d", 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("<â°í> â°í·Î ¿Å±æ ¼ö ¾ø´Â ¾ÆÀÌÅÛ ÀÔ´Ï´Ù.")); return; } if (true == pkItem->IsEquipped()) { ch->ChatPacket(CHAT_TYPE_INFO, " Giyili Item Depolanamaz : %s", ch->GetName()); return; } if (!pkSafebox->IsEmpty(p->bSafePos, pkItem->GetSize())) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> ¿Å±æ ¼ö ¾ø´Â À§Ä¡ÀÔ´Ï´Ù.")); return; } if (pkItem->GetVnum() == UNIQUE_ITEM_SAFEBOX_EXPAND) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> ÀÌ ¾ÆÀÌÅÛÀº ³ÖÀ» ¼ö ¾ø½À´Ï´Ù.")); return; } if( IS_SET(pkItem->GetAntiFlag(), ITEM_ANTIFLAG_SAFEBOX) ) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> ÀÌ ¾ÆÀÌÅÛÀº ³ÖÀ» ¼ö ¾ø½À´Ï´Ù.")); return; } if (true == pkItem->isLocked()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> ÀÌ ¾ÆÀÌÅÛÀº ³ÖÀ» ¼ö ¾ø½À´Ï´Ù.")); return; } #ifdef __SOUL_BIND_SYSTEM__ if (pkItem->IsSealed()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("This product is sealed, you can not put it in storage.")); return; } #endif 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("<â°í> ¿Å±æ ¼ö ¾ø´Â À§Ä¡ÀÔ´Ï´Ù.")); 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("<â°í> ¿Å±æ ¼ö ¾ø´Â À§Ä¡ÀÔ´Ï´Ù.")); 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("<â°í> ¿Å±æ ¼ö ¾ø´Â À§Ä¡ÀÔ´Ï´Ù.")); return; } pkSafebox->Remove(p->bSafePos); 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("´ë·ÃÀå¿¡¼­ »ç¿ëÇÏ½Ç ¼ö ¾ø½À´Ï´Ù.")); return; } TPacketCGPartyInvite * p = (TPacketCGPartyInvite*) c_pData; LPCHARACTER pInvitee = CHARACTER_MANAGER::instance().Find(p->vid); if (!pInvitee || !ch->GetDesc() || !pInvitee->GetDesc()) { sys_err("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("´ë·ÃÀå¿¡¼­ »ç¿ëÇÏ½Ç ¼ö ¾ø½À´Ï´Ù.")); 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("<ÆÄƼ> ÆÄƼ¿äûÀ» ÇÑ Ä³¸¯Å͸¦ ãÀ»¼ö ¾ø½À´Ï´Ù.")); 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("<ÆÄƼ> ¼­¹ö ¹®Á¦·Î ÆÄƼ °ü·Ã 󸮸¦ ÇÒ ¼ö ¾ø½À´Ï´Ù.")); return; } TPacketCGPartySetState* p = (TPacketCGPartySetState*) c_pData; if (!ch->GetParty()) return; if (ch->GetParty()->GetLeaderPID() != ch->GetPlayerID()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ¸®´õ¸¸ º¯°æÇÒ ¼ö ÀÖ½À´Ï´Ù.")); return; } if (!ch->GetParty()->IsMember(p->pid)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> »óŸ¦ º¯°æÇÏ·Á´Â »ç¶÷ÀÌ ÆÄƼ¿øÀÌ ¾Æ´Õ´Ï´Ù.")); return; } DWORD pid = p->pid; sys_log(0, "PARTY SetRole pid %d to role %d state %s", 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("<ÆÄƼ> ¾îÅÂÄ¿ ¼³Á¤¿¡ ½ÇÆĞÇÏ¿´½À´Ï´Ù.")); */ break; default: sys_err("wrong byRole in PartySetState Packet name %s state %d", ch->GetName(), p->byRole); break; } } void CInputMain::PartyRemove(LPCHARACTER ch, const char* c_pData) { if (ch->GetArena()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´ë·ÃÀå¿¡¼­ »ç¿ëÇÏ½Ç ¼ö ¾ø½À´Ï´Ù.")); return; } if (!CPartyManager::instance().IsEnablePCParty()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ¼­¹ö ¹®Á¦·Î ÆÄƼ °ü·Ã 󸮸¦ ÇÒ ¼ö ¾ø½À´Ï´Ù.")); return; } if (ch->GetDungeon()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´øÀü ¾È¿¡¼­´Â ÆÄƼ¿¡¼­ Ãß¹æÇÒ ¼ö ¾ø½À´Ï´Ù.")); 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("<ÆÄƼ> ´øÁ¯³»¿¡¼­´Â ÆÄƼ¿øÀ» Ãß¹æÇÒ ¼ö ¾ø½À´Ï´Ù.")); } else { // Àû·æ¼º¿¡¼­ ÆÄƼÀåÀÌ ´øÁ¯ ¹Û¿¡¼­ ÆÄƼ ÇØ»ê ¸øÇÏ°Ô ¸·ÀÚ if(pParty->IsPartyInDungeon(351)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ>´øÀü ¾È¿¡ ÆÄƼ¿øÀÌ ÀÖ¾î ÆÄƼ¸¦ ÇØ»ê ÇÒ ¼ö ¾ø½À´Ï´Ù.")); return; } // 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("<ÆÄƼ> ÆÄƼ¿¡¼­ Ãß¹æ´çÇϼ̽À´Ï´Ù.")); //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("<ÆÄƼ> ´øÁ¯³»¿¡¼­´Â ÆÄƼ¸¦ ³ª°¥ ¼ö ¾ø½À´Ï´Ù.")); } else { if (pParty->GetMemberCount() == 2) { // party disband CPartyManager::instance().DeleteParty(pParty); } else { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ¿¡¼­ ³ª°¡¼Ì½À´Ï´Ù.")); //pParty->SendPartyRemoveOneToAll(ch); pParty->Quit(ch->GetPlayerID()); //pParty->SendPartyRemoveAllToOne(ch); //CPartyManager::instance().SetPartyMember(ch->GetPlayerID(), NULL); } } } else { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´Ù¸¥ ÆÄƼ¿øÀ» Å»Åğ½Ãų ¼ö ¾ø½À´Ï´Ù.")); } } } void CInputMain::AnswerMakeGuild(LPCHARACTER ch, const char* c_pData) { TPacketCGAnswerMakeGuild* p = (TPacketCGAnswerMakeGuild*) c_pData; if (ch->GetGold() < 200000) { ch->ChatPacket(CHAT_TYPE_INFO, "Yetersiz yang!"); return; } if (ch->GetLevel() < 40) { ch->ChatPacket(CHAT_TYPE_INFO, "Yetersiz level!"); return; } if (get_global_time() - ch->GetQuestFlag("guild_manage.new_disband_time") < CGuildManager::instance().GetDisbandDelay()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ÇØ»êÇÑ ÈÄ %dÀÏ À̳»¿¡´Â ±æµå¸¦ ¸¸µé ¼ö ¾ø½À´Ï´Ù."), 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("<±æµå> Å»ÅğÇÑ ÈÄ %dÀÏ À̳»¿¡´Â ±æµå¸¦ ¸¸µé ¼ö ¾ø½À´Ï´Ù."), 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("ÀûÇÕÇÏÁö ¾ÊÀº ±æµå À̸§ ÀÔ´Ï´Ù.")); return; } DWORD dwGuildID = gm.CreateGuild(cp); if (dwGuildID) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> [%s] ±æµå°¡ »ı¼ºµÇ¾ú½À´Ï´Ù."), 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("<±æµå> ±æµå »ı¼º¿¡ ½ÇÆĞÇÏ¿´½À´Ï´Ù.")); } 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("<ÆÄƼ> ÆÄƼ ±â¼úÀº ÆÄƼÀ常 »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù.")); 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("<ÆÄƼ> ¼ÒȯÇÏ·Á´Â ´ë»óÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù.")); } 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(data); const char* c_pData = data + sizeof(TPacketCGGuild); uiBytes -= sizeof(TPacketCGGuild); const GUILD_SUBHEADER_CG SubHeader = static_cast(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("<±æµå> ±æµå¿¡ ¼ÓÇØÀÖÁö ¾Ê½À´Ï´Ù.")); return SubPacketLen; } } switch (SubHeader) { case GUILD_SUBHEADER_CG_DEPOSIT_MONEY: { // by mhh : ±æµåÀÚ±İÀº ´çºĞ°£ ³ÖÀ» ¼ö ¾ø´Ù. return SubPacketLen; const int gold = MIN(*reinterpret_cast(c_pData), __deposit_limit()); if (gold < 0) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> À߸øµÈ ±İ¾×ÀÔ´Ï´Ù.")); return SubPacketLen; } if (ch->GetGold() < gold) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> °¡Áö°í ÀÖ´Â µ·ÀÌ ºÎÁ·ÇÕ´Ï´Ù.")); return SubPacketLen; } pGuild->RequestDepositMoney(ch, gold); } return SubPacketLen; case GUILD_SUBHEADER_CG_WITHDRAW_MONEY: { // by mhh : ±æµåÀÚ±İÀº ´çºĞ°£ »¬ ¼ö ¾ø´Ù. return SubPacketLen; const int gold = MIN(*reinterpret_cast(c_pData), 500000); if (gold < 0) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> À߸øµÈ ±İ¾×ÀÔ´Ï´Ù.")); return SubPacketLen; } pGuild->RequestWithdrawMoney(ch, gold); } return SubPacketLen; case GUILD_SUBHEADER_CG_ADD_MEMBER: { const DWORD vid = *reinterpret_cast(c_pData); LPCHARACTER newmember = CHARACTER_MANAGER::instance().Find(vid); if (!newmember) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±×·¯ÇÑ »ç¶÷À» ãÀ» ¼ö ¾ø½À´Ï´Ù.")); 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("<±æµå> ¾ÆÁ÷ °¡ÀÔÇÒ ¼ö ¾ø´Â ij¸¯ÅÍÀÔ´Ï´Ù")); 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("<±æµå> ±æµåÀü Áß¿¡´Â ±æµå¿øÀ» Å»Åğ½Ãų ¼ö ¾ø½À´Ï´Ù.")); return SubPacketLen; } const DWORD pid = *reinterpret_cast(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("<±æµå> »ó´ë¹æÀÌ °°Àº ±æµå°¡ ¾Æ´Õ´Ï´Ù.")); return SubPacketLen; } if (!pGuild->HasGradeAuth(m->grade, GUILD_AUTH_REMOVE_MEMBER)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµå¿øÀ» °­Á¦ Å»Åğ ½Ãų ±ÇÇÑÀÌ ¾ø½À´Ï´Ù.")); 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("<±æµå> ±æµå¿øÀ» °­Á¦ Å»Åğ ½Ãų ±ÇÇÑÀÌ ¾ø½À´Ï´Ù.")); return SubPacketLen; } if (pGuild->RequestRemoveMember(pid)) ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµå¿øÀ» °­Á¦ Å»Åğ ½ÃÄ×½À´Ï´Ù.")); else ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±×·¯ÇÑ »ç¶÷À» ãÀ» ¼ö ¾ø½À´Ï´Ù.")); } } 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("<±æµå> Á÷À§ À̸§À» º¯°æÇÒ ±ÇÇÑÀÌ ¾ø½À´Ï´Ù.")); } else if (*c_pData == GUILD_LEADER_GRADE) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµåÀåÀÇ Á÷À§ À̸§Àº º¯°æÇÒ ¼ö ¾ø½À´Ï´Ù.")); } else if (!check_name(gradename)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ÀûÇÕÇÏÁö ¾ÊÀº Á÷À§ À̸§ ÀÔ´Ï´Ù.")); } 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("<±æµå> Á÷À§ ±ÇÇÑÀ» º¯°æÇÒ ±ÇÇÑÀÌ ¾ø½À´Ï´Ù.")); } else if (*c_pData == GUILD_LEADER_GRADE) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµåÀåÀÇ ±ÇÇÑÀº º¯°æÇÒ ¼ö ¾ø½À´Ï´Ù.")); } else { pGuild->ChangeGradeAuth(*c_pData, *(c_pData + 1)); } } return SubPacketLen; case GUILD_SUBHEADER_CG_OFFER: { DWORD offer = *reinterpret_cast(c_pData); if (pGuild->GetLevel() >= GUILD_MAX_LEVEL && LC_IsHongKong() == false) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµå°¡ ÀÌ¹Ì ÃÖ°í ·¹º§ÀÔ´Ï´Ù.")); } else { offer /= 100; offer *= 100; if (pGuild->OfferExp(ch, offer)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> %uÀÇ °æÇèÄ¡¸¦ ÅõÀÚÇÏ¿´½À´Ï´Ù."), offer); } else { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> °æÇèÄ¡ ÅõÀÚ¿¡ ½ÇÆĞÇÏ¿´½À´Ï´Ù.")); } } } return SubPacketLen; case GUILD_SUBHEADER_CG_CHARGE_GSP: { const int offer = *reinterpret_cast(c_pData); const int gold = offer * 100; if (offer < 0 || gold < offer || gold < 0 || ch->GetGold() < gold) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> µ·ÀÌ ºÎÁ·ÇÕ´Ï´Ù.")); return SubPacketLen; } if (!pGuild->ChargeSP(ch, offer)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ¿ë½Å·Â ȸº¹¿¡ ½ÇÆĞÇÏ¿´½À´Ï´Ù.")); } } return SubPacketLen; case GUILD_SUBHEADER_CG_POST_COMMENT: { const size_t length = *c_pData; if (length > GUILD_COMMENT_MAX_LEN) { // À߸øµÈ ±æÀÌ.. ²÷¾îÁÖÀÚ. sys_err("POST_COMMENT: %s comment too long (length: %u)", 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("<±æµå> °øÁö±ÛÀ» ÀÛ¼ºÇÒ ±ÇÇÑÀÌ ¾ø½À´Ï´Ù.")); } 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(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(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("<±æµå> Á÷À§¸¦ º¯°æÇÒ ±ÇÇÑÀÌ ¾ø½À´Ï´Ù.")); else if (ch->GetPlayerID() == pid) ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµåÀåÀÇ Á÷À§´Â º¯°æÇÒ ¼ö ¾ø½À´Ï´Ù.")); else if (grade == 1) ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµåÀåÀ¸·Î Á÷À§¸¦ º¯°æÇÒ ¼ö ¾ø½À´Ï´Ù.")); else pGuild->ChangeMemberGrade(pid, grade); } return SubPacketLen; case GUILD_SUBHEADER_CG_USE_SKILL: { const TPacketCGGuildUseSkill* p = reinterpret_cast(c_pData); pGuild->UseSkill(p->dwVnum, ch, p->dwPID); } return SubPacketLen; case GUILD_SUBHEADER_CG_CHANGE_MEMBER_GENERAL: { const DWORD pid = *reinterpret_cast(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("<±æµå> À屺À» ÁöÁ¤ÇÒ ±ÇÇÑÀÌ ¾ø½À´Ï´Ù.")); } else { if (!pGuild->ChangeMemberGeneral(pid, is_general)) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ´õÀÌ»ó Àå¼ö¸¦ ÁöÁ¤ÇÒ ¼ö ¾ø½À´Ï´Ù.")); } } } return SubPacketLen; case GUILD_SUBHEADER_CG_GUILD_INVITE_ANSWER: { const DWORD guild_id = *reinterpret_cast(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("¾ÆÀÌÅÛÀ» °Ç³×ÁÙ ¼ö ¾ø½À´Ï´Ù.")); } void CInputMain::Hack(LPCHARACTER ch, const char * c_pData) { TPacketCGHack * p = (TPacketCGHack *) c_pData; char buf[sizeof(p->szBuf)]; strlcpy(buf, p->szBuf, sizeof(buf)); sys_err("HACK_DETECT: %s %s", ch->GetName(), buf); // ÇöÀç Ŭ¶óÀ̾ğÆ®¿¡¼­ ÀÌ ÆĞŶÀ» º¸³»´Â °æ¿ì°¡ ¾øÀ¸¹Ç·Î ¹«Á¶°Ç ²÷µµ·Ï ÇÑ´Ù ch->GetDesc()->SetPhase(PHASE_CLOSE); } int CInputMain::MyShop(LPCHARACTER ch, const char * c_pData, size_t uiBytes) { TPacketCGMyShop * p = (TPacketCGMyShop *) c_pData; int iExtraLen = p->bCount * sizeof(TShopItemTable); #ifdef SHOP_BLOCK_GAME99 if (g_bChannel >= 99 && ch->GetGMLevel() <= 0) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "SHOP_OX_ERROR")); return (iExtraLen); } #endif #ifdef OFFLINE_SHOP if (quest::CQuestManager::instance().GetEventFlag("shop_off")==1) if (ch) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT( "SHOP_TEMP_OFF")); return (iExtraLen); } #endif #ifdef SHOP_GM_PRIVILEGES if (GM_PLAYER < ch->GetGMLevel() && SHOP_GM_PRIVILEGES >ch->GetGMLevel()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("SHOP_PRIV_ERROR")); return (iExtraLen); } #endif if (uiBytes < sizeof(TPacketCGMyShop) + iExtraLen) return -1; #ifndef FULL_YANG if (ch->GetGold() >= GOLD_MAX) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¼ÒÀ¯ µ·ÀÌ 20¾ï³ÉÀ» ³Ñ¾î °Å·¡¸¦ ÇÛ¼ö°¡ ¾ø½À´Ï´Ù.")); sys_log(0, "MyShop ==> OverFlow Gold id %u name %s ", ch->GetPlayerID(), ch->GetName()); return (iExtraLen); } #endif if (ch->IsStun() || ch->IsDead()) return (iExtraLen); if (ch->GetExchange() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->IsCubeOpen()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´Ù¸¥ °Å·¡ÁßÀÏ°æ¿ì °³ÀλóÁ¡À» ¿­¼ö°¡ ¾ø½À´Ï´Ù.")); return (iExtraLen); } sys_log(0, "MyShop count %d", p->bCount); #ifdef __ENABLE_SHOP_DECORATION_SYSTEM__ ch->OpenMyShop(p->szSign, (TShopItemTable *)(c_pData + sizeof(TPacketCGMyShop)), p->bCount, p->days, p->dwKasmirNpc, p->bKasmirBaslik); #else ch->OpenMyShop(p->szSign, (TShopItemTable *)(c_pData + sizeof(TPacketCGMyShop)), p->bCount); #endif return (iExtraLen); } void CInputMain::Refine(LPCHARACTER ch, const char* c_pData) { const TPacketCGRefine* p = reinterpret_cast(c_pData); if (ch->GetExchange() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->GetMyShop() || ch->IsCubeOpen()) { ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("â°í,°Å·¡Ã¢µîÀÌ ¿­¸° »óÅ¿¡¼­´Â °³·®À» ÇÒ¼ö°¡ ¾ø½À´Ï´Ù")); 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) { sys_log (0, "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) { sys_log (0, "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, "»ç±Í Ÿ¿ö ¿Ï·á º¸»óÀº Çѹø±îÁö »ç¿ë°¡´ÉÇÕ´Ï´Ù."); } } } } ch->ClearRefineMode(); } int CInputMain::Analyze(LPDESC d, BYTE bHeader, const char * c_pData) { LPCHARACTER ch; if (!(ch = d->GetCharacter())) { sys_err("no character on desc"); d->SetPhase(PHASE_CLOSE); return (0); } int iExtraLen = 0; if (test_server && bHeader != HEADER_CG_MOVE) sys_log(0, "CInputMain::Analyze() ==> Header [%d] ", 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; sys_log(0, "%s", 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("Ŭ¶óÀ̾ğÆ® ¹öÀüÀÌ Æ²·Á ·Î±×¾Æ¿ô µË´Ï´Ù. Á¤»óÀûÀ¸·Î ÆĞÄ¡ ÈÄ Á¢¼ÓÇϼ¼¿ä.")); d->DelayedDisconnect(10); LogManager::instance().HackLog("VERSION_CONFLICT", d->GetAccountTable().login, ch->GetName(), d->GetHostName()); } } } else { if (!*d->GetClientVersion()) { sys_err("Version not recieved name %s", 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; #ifdef __NEW_DROP_DIALOG__ case HEADER_CG_ITEM_DESTROY: if (!ch->IsObserverMode()) ItemDestroy(ch, c_pData); break; #endif 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; #ifdef OFFLINE_MESSAGE case HEADER_CG_OFFLINE_WHISPER: OfflineWhisper(ch, c_pData); break; #endif // 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_HACK: Hack(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; #ifdef __ENABLE_SHOP_SEARCH_SYSTEM__ case HEADER_CG_SHOP_SEARCH: ShopSearch(ch, c_pData, false); break; case HEADER_CG_SHOP_SEARCH_SUB: ShopSearch(ch, c_pData, true); break; case HEADER_CG_SHOP_SEARCH_BUY: ShopSearchBuy(ch, c_pData); break; #endif case HEADER_CG_HS_ACK: if (isHackShieldEnable) { CHackShieldManager::instance().VerifyAck(d->GetCharacter(), c_pData); } break; case HEADER_CG_XTRAP_ACK: { TPacketXTrapCSVerify* p = reinterpret_cast((void*)c_pData); CXTrapManager::instance().Verify_CSStep3(d->GetCharacter(), p->bPacketData); } break; case HEADER_CG_DRAGON_SOUL_REFINE: { TPacketCGDragonSoulRefine* p = reinterpret_cast ((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; } } #ifdef ENABLE_SWITCHBOT case HEADER_CG_SWITCHBOT: if ((iExtraLen = Switchbot(ch, c_pData, m_iBufferLeft)) < 0) { return -1; } break; #endif break; } return (iExtraLen); } int CInputDead::Analyze(LPDESC d, BYTE bHeader, const char * c_pData) { LPCHARACTER ch; if (!(ch = d->GetCharacter())) { sys_err("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; case HEADER_CG_HACK: Hack(ch, c_pData); break; default: return (0); } return (iExtraLen); } #ifdef ENABLE_SWITCHBOT int CInputMain::Switchbot(LPCHARACTER ch, const char* data, size_t uiBytes) { const TPacketCGSwitchbot* p = reinterpret_cast(data); if (uiBytes < sizeof(TPacketCGSwitchbot)) { return -1; } const char* c_pData = data + sizeof(TPacketCGSwitchbot); uiBytes -= sizeof(TPacketCGSwitchbot); switch (p->subheader) { case SUBHEADER_CG_SWITCHBOT_START: { size_t extraLen = sizeof(TSwitchbotAttributeAlternativeTable) * SWITCHBOT_ALTERNATIVE_COUNT; if (uiBytes < extraLen) { return -1; } std::vector vec_alternatives; for (BYTE alternative = 0; alternative < SWITCHBOT_ALTERNATIVE_COUNT; ++alternative) { const TSwitchbotAttributeAlternativeTable* pAttr = reinterpret_cast(c_pData); c_pData += sizeof(TSwitchbotAttributeAlternativeTable); vec_alternatives.emplace_back(*pAttr); } CSwitchbotManager::Instance().Start(ch->GetPlayerID(), p->slot, vec_alternatives); return extraLen; } case SUBHEADER_CG_SWITCHBOT_STOP: { CSwitchbotManager::Instance().Stop(ch->GetPlayerID(), p->slot); return 0; } } return 0; } #endif