Guest User

input_main.cpp

a guest
Jun 6th, 2018
325
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 101.38 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include "constants.h"
  3. #include "config.h"
  4. #include "utils.h"
  5. #include "desc_client.h"
  6. #include "desc_manager.h"
  7. #include "buffer_manager.h"
  8. #include "packet.h"
  9. #include "protocol.h"
  10. #include "char.h"
  11. #include "char_manager.h"
  12. #include "item.h"
  13. #include "item_manager.h"
  14. #include "cmd.h"
  15. #include "shop.h"
  16. #include "shop_manager.h"
  17. #include "safebox.h"
  18. #include "regen.h"
  19. #include "battle.h"
  20. #include "exchange.h"
  21. #include "questmanager.h"
  22. #include "profiler.h"
  23. #include "messenger_manager.h"
  24. #include "party.h"
  25. #include "p2p.h"
  26. #include "affect.h"
  27. #include "guild.h"
  28. #include "guild_manager.h"
  29. #include "log.h"
  30. #include "banword.h"
  31. #include "empire_text_convert.h"
  32. #include "unique_item.h"
  33. #include "building.h"
  34. #include "locale_service.h"
  35. #include "gm.h"
  36. #include "spam.h"
  37. #include "ani.h"
  38. #include "motion.h"
  39. #include "OXEvent.h"
  40. #include "locale_service.h"
  41. #include "HackShield.h"
  42. #include "XTrapManager.h"
  43. #include "DragonSoul.h"
  44. #include "offline_shop.h"
  45. #include "offlineshop_manager.h"
  46. #include "belt_inventory_helper.h" // @fixme119
  47. #include "../../common/CommonDefines.h"
  48.  
  49. #include "input.h"
  50.  
  51. #define ENABLE_CHAT_COLOR_SYSTEM
  52. #define ENABLE_CHAT_LOGGING
  53. #define ENABLE_CHAT_SPAMLIMIT
  54. #define ENABLE_WHISPER_CHAT_SPAMLIMIT
  55. #define ENABLE_CHECK_GHOSTMODE
  56.  
  57. #ifdef ENABLE_CHAT_LOGGING
  58. static char __escape_string[1024];
  59. static char __escape_string2[1024];
  60. #endif
  61.  
  62. static int __deposit_limit()
  63. {
  64.     return (1000*10000); // 1õ¸¸
  65. }
  66.  
  67. void SendBlockChatInfo(LPCHARACTER ch, int sec)
  68. {
  69.     if (sec <= 0)
  70.     {
  71.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("äÆÃ ±ÝÁö »óÅÂÀÔ´Ï´Ù."));
  72.         return;
  73.     }
  74.  
  75.     long hour = sec / 3600;
  76.     sec -= hour * 3600;
  77.  
  78.     long min = (sec / 60);
  79.     sec -= min * 60;
  80.  
  81.     char buf[128+1];
  82.  
  83.     if (hour > 0 && min > 0)
  84.         snprintf(buf, sizeof(buf), LC_TEXT("%d ½Ã°£ %d ºÐ %d ÃÊ µ¿¾È äÆÃ±ÝÁö »óÅÂÀÔ´Ï´Ù"), hour, min, sec);
  85.     else if (hour > 0 && min == 0)
  86.         snprintf(buf, sizeof(buf), LC_TEXT("%d ½Ã°£ %d ÃÊ µ¿¾È äÆÃ±ÝÁö »óÅÂÀÔ´Ï´Ù"), hour, sec);
  87.     else if (hour == 0 && min > 0)
  88.         snprintf(buf, sizeof(buf), LC_TEXT("%d ºÐ %d ÃÊ µ¿¾È äÆÃ±ÝÁö »óÅÂÀÔ´Ï´Ù"), min, sec);
  89.     else
  90.         snprintf(buf, sizeof(buf), LC_TEXT("%d ÃÊ µ¿¾È äÆÃ±ÝÁö »óÅÂÀÔ´Ï´Ù"), sec);
  91.  
  92.     ch->ChatPacket(CHAT_TYPE_INFO, buf);
  93. }
  94.  
  95. EVENTINFO(spam_event_info)
  96. {
  97.     char host[MAX_HOST_LENGTH+1];
  98.  
  99.     spam_event_info()
  100.     {
  101.         ::memset( host, 0, MAX_HOST_LENGTH+1 );
  102.     }
  103. };
  104.  
  105. typedef boost::unordered_map<std::string, std::pair<unsigned int, LPEVENT> > spam_score_of_ip_t;
  106. spam_score_of_ip_t spam_score_of_ip;
  107.  
  108. EVENTFUNC(block_chat_by_ip_event)
  109. {
  110.     spam_event_info* info = dynamic_cast<spam_event_info*>( event->info );
  111.  
  112.     if ( info == NULL )
  113.     {
  114.         sys_err( "block_chat_by_ip_event> <Factor> Null pointer" );
  115.         return 0;
  116.     }
  117.  
  118.     const char * host = info->host;
  119.  
  120.     spam_score_of_ip_t::iterator it = spam_score_of_ip.find(host);
  121.  
  122.     if (it != spam_score_of_ip.end())
  123.     {
  124.         it->second.first = 0;
  125.         it->second.second = NULL;
  126.     }
  127.  
  128.     return 0;
  129. }
  130.  
  131. bool SpamBlockCheck(LPCHARACTER ch, const char* const buf, const size_t buflen)
  132. {
  133.     if (ch->GetLevel() < g_iSpamBlockMaxLevel)
  134.     {
  135.         spam_score_of_ip_t::iterator it = spam_score_of_ip.find(ch->GetDesc()->GetHostName());
  136.  
  137.         if (it == spam_score_of_ip.end())
  138.         {
  139.             spam_score_of_ip.insert(std::make_pair(ch->GetDesc()->GetHostName(), std::make_pair(0, (LPEVENT) NULL)));
  140.             it = spam_score_of_ip.find(ch->GetDesc()->GetHostName());
  141.         }
  142.  
  143.         if (it->second.second)
  144.         {
  145.             SendBlockChatInfo(ch, event_time(it->second.second) / passes_per_sec);
  146.             return true;
  147.         }
  148.  
  149.         unsigned int score;
  150.         const char * word = SpamManager::instance().GetSpamScore(buf, buflen, score);
  151.  
  152.         it->second.first += score;
  153.  
  154.         if (word)
  155.             sys_log(0, "SPAM_SCORE: %s text: %s score: %u total: %u word: %s", ch->GetName(), buf, score, it->second.first, word);
  156.  
  157.         if (it->second.first >= g_uiSpamBlockScore)
  158.         {
  159.             spam_event_info* info = AllocEventInfo<spam_event_info>();
  160.             strlcpy(info->host, ch->GetDesc()->GetHostName(), sizeof(info->host));
  161.  
  162.             it->second.second = event_create(block_chat_by_ip_event, info, PASSES_PER_SEC(g_uiSpamBlockDuration));
  163.             sys_log(0, "SPAM_IP: %s for %u seconds", info->host, g_uiSpamBlockDuration);
  164.  
  165.             LogManager::instance().CharLog(ch, 0, "SPAM", word);
  166.  
  167.             SendBlockChatInfo(ch, event_time(it->second.second) / passes_per_sec);
  168.  
  169.             return true;
  170.         }
  171.     }
  172.  
  173.     return false;
  174. }
  175.  
  176. enum
  177. {
  178.     TEXT_TAG_PLAIN,
  179.     TEXT_TAG_TAG, // ||
  180.     TEXT_TAG_COLOR, // |cffffffff
  181.     TEXT_TAG_HYPERLINK_START, // |H
  182.     TEXT_TAG_HYPERLINK_END, // |h ex) |Hitem:1234:1:1:1|h
  183.     TEXT_TAG_RESTORE_COLOR,
  184. };
  185.  
  186. int GetTextTag(const char * src, int maxLen, int & tagLen, std::string & extraInfo)
  187. {
  188.     tagLen = 1;
  189.  
  190.     if (maxLen < 2 || *src != '|')
  191.         return TEXT_TAG_PLAIN;
  192.  
  193.     const char * cur = ++src;
  194.  
  195.     if (*cur == '|') // ||´Â |·Î Ç¥½ÃÇÑ´Ù.
  196.     {
  197.         tagLen = 2;
  198.         return TEXT_TAG_TAG;
  199.     }
  200.     else if (*cur == 'c') // color |cffffffffblahblah|r
  201.     {
  202.         tagLen = 2;
  203.         return TEXT_TAG_COLOR;
  204.     }
  205.     else if (*cur == 'H') // hyperlink |Hitem:10000:0:0:0:0|h[À̸§]|h
  206.     {
  207.         tagLen = 2;
  208.         return TEXT_TAG_HYPERLINK_START;
  209.     }
  210.     else if (*cur == 'h') // end of hyperlink
  211.     {
  212.         tagLen = 2;
  213.         return TEXT_TAG_HYPERLINK_END;
  214.     }
  215.  
  216.     return TEXT_TAG_PLAIN;
  217. }
  218.  
  219. void GetTextTagInfo(const char * src, int src_len, int & hyperlinks, bool & colored)
  220. {
  221.     colored = false;
  222.     hyperlinks = 0;
  223.  
  224.     int len;
  225.     std::string extraInfo;
  226.  
  227.     for (int i = 0; i < src_len;)
  228.     {
  229.         int tag = GetTextTag(&src[i], src_len - i, len, extraInfo);
  230.  
  231.         if (tag == TEXT_TAG_HYPERLINK_START)
  232.             ++hyperlinks;
  233.  
  234.         if (tag == TEXT_TAG_COLOR)
  235.             colored = true;
  236.  
  237.         i += len;
  238.     }
  239. }
  240.  
  241. int ProcessTextTag(LPCHARACTER ch, const char * c_pszText, size_t len)
  242. {
  243.     //°³ÀλóÁ¡Áß¿¡ ±Ý°­°æÀ» »ç¿ëÇÒ °æ¿ì
  244.     //0 : Á¤»óÀûÀ¸·Î »ç¿ë
  245.     //1 : ±Ý°­°æ ºÎÁ·
  246.     //2 : ±Ý°­°æÀÌ ÀÖÀ¸³ª, °³ÀλóÁ¡¿¡¼­ »ç¿ëÁß
  247.     //3 : ±âŸ
  248.     //4 : ¿¡·¯
  249.     int hyperlinks;
  250.     bool colored;
  251.  
  252.     GetTextTagInfo(c_pszText, len, hyperlinks, colored);
  253.  
  254.     if (colored == true && hyperlinks == 0)
  255.         return 4;
  256.  
  257. #ifdef ENABLE_NEWSTUFF
  258.     if (g_bDisablePrismNeed)
  259.         return 0;
  260. #endif
  261.     int nPrismCount = ch->CountSpecifyItem(ITEM_PRISM);
  262.  
  263.     if (nPrismCount < hyperlinks)
  264.         return 1;
  265.  
  266.  
  267.     if (!ch->GetMyShop())
  268.     {
  269.         ch->RemoveSpecifyItem(ITEM_PRISM, hyperlinks);
  270.         return 0;
  271.     } else
  272.     {
  273.         int sellingNumber = ch->GetMyShop()->GetNumberByVnum(ITEM_PRISM);
  274.         if(nPrismCount - sellingNumber < hyperlinks)
  275.         {
  276.             return 2;
  277.         } else
  278.         {
  279.             ch->RemoveSpecifyItem(ITEM_PRISM, hyperlinks);
  280.             return 0;
  281.         }
  282.     }
  283.  
  284.     return 4;
  285. }
  286.  
  287. int CInputMain::Whisper(LPCHARACTER ch, const char * data, size_t uiBytes)
  288. {
  289.     const TPacketCGWhisper* pinfo = reinterpret_cast<const TPacketCGWhisper*>(data);
  290.  
  291.     if (uiBytes < pinfo->wSize)
  292.         return -1;
  293.  
  294.     int iExtraLen = pinfo->wSize - sizeof(TPacketCGWhisper);
  295.  
  296.     if (iExtraLen < 0)
  297.     {
  298.         sys_err("invalid packet length (len %d size %u buffer %u)", iExtraLen, pinfo->wSize, uiBytes);
  299.         ch->GetDesc()->SetPhase(PHASE_CLOSE);
  300.         return -1;
  301.     }
  302.  
  303. #ifdef ENABLE_WHISPER_CHAT_SPAMLIMIT
  304.     if (ch->IncreaseChatCounter() >= 10)
  305.     {
  306.         ch->GetDesc()->DelayedDisconnect(0);
  307.         return (iExtraLen);
  308.     }
  309. #endif
  310.  
  311.     if (ch->FindAffect(AFFECT_BLOCK_CHAT))
  312.     {
  313.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("äÆÃ ±ÝÁö »óÅÂÀÔ´Ï´Ù."));
  314.         return (iExtraLen);
  315.     }
  316.  
  317.     LPCHARACTER pkChr = CHARACTER_MANAGER::instance().FindPC(pinfo->szNameTo);
  318.  
  319.     if (pkChr == ch)
  320.         return (iExtraLen);
  321.  
  322.     LPDESC pkDesc = NULL;
  323.  
  324.     BYTE bOpponentEmpire = 0;
  325.  
  326.     if (test_server)
  327.     {
  328.         if (!pkChr)
  329.             sys_log(0, "Whisper to %s(%s) from %s", "Null", pinfo->szNameTo, ch->GetName());
  330.         else
  331.             sys_log(0, "Whisper to %s(%s) from %s", pkChr->GetName(), pinfo->szNameTo, ch->GetName());
  332.     }
  333.  
  334.     if (ch->IsBlockMode(BLOCK_WHISPER))
  335.     {
  336.         if (ch->GetDesc())
  337.         {
  338.             TPacketGCWhisper pack;
  339.             pack.bHeader = HEADER_GC_WHISPER;
  340.             pack.bType = WHISPER_TYPE_SENDER_BLOCKED;
  341.             pack.wSize = sizeof(TPacketGCWhisper);
  342.             strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
  343.             ch->GetDesc()->Packet(&pack, sizeof(pack));
  344.         }
  345.         return iExtraLen;
  346.     }
  347.  
  348.     if (!pkChr)
  349.     {
  350.         CCI * pkCCI = P2P_MANAGER::instance().Find(pinfo->szNameTo);
  351.  
  352.         if (pkCCI)
  353.         {
  354.             pkDesc = pkCCI->pkDesc;
  355.             pkDesc->SetRelay(pinfo->szNameTo);
  356.             bOpponentEmpire = pkCCI->bEmpire;
  357.  
  358.             if (test_server)
  359.                 sys_log(0, "Whisper to %s from %s (Channel %d Mapindex %d)", "Null", ch->GetName(), pkCCI->bChannel, pkCCI->lMapIndex);
  360.         }
  361.     }
  362.     else
  363.     {
  364.         pkDesc = pkChr->GetDesc();
  365.         bOpponentEmpire = pkChr->GetEmpire();
  366.     }
  367.  
  368.     if (!pkDesc)
  369.     {
  370.         if (ch->GetDesc())
  371.         {
  372.             TPacketGCWhisper pack;
  373.  
  374.             pack.bHeader = HEADER_GC_WHISPER;
  375.             pack.bType = WHISPER_TYPE_NOT_EXIST;
  376.             pack.wSize = sizeof(TPacketGCWhisper);
  377.             strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
  378.             ch->GetDesc()->Packet(&pack, sizeof(TPacketGCWhisper));
  379.             sys_log(0, "WHISPER: no player");
  380.         }
  381.     }
  382.     else
  383.     {
  384.         if (ch->IsBlockMode(BLOCK_WHISPER))
  385.         {
  386.             if (ch->GetDesc())
  387.             {
  388.                 TPacketGCWhisper pack;
  389.                 pack.bHeader = HEADER_GC_WHISPER;
  390.                 pack.bType = WHISPER_TYPE_SENDER_BLOCKED;
  391.                 pack.wSize = sizeof(TPacketGCWhisper);
  392.                 strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
  393.                 ch->GetDesc()->Packet(&pack, sizeof(pack));
  394.             }
  395.         }
  396.         else if (pkChr && pkChr->IsBlockMode(BLOCK_WHISPER))
  397.         {
  398.             if (ch->GetDesc())
  399.             {
  400.                 TPacketGCWhisper pack;
  401.                 pack.bHeader = HEADER_GC_WHISPER;
  402.                 pack.bType = WHISPER_TYPE_TARGET_BLOCKED;
  403.                 pack.wSize = sizeof(TPacketGCWhisper);
  404.                 strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
  405.                 ch->GetDesc()->Packet(&pack, sizeof(pack));
  406.             }
  407.         }
  408.         else
  409.         {
  410.             BYTE bType = WHISPER_TYPE_NORMAL;
  411.  
  412.             char buf[CHAT_MAX_LEN + 1];
  413.             strlcpy(buf, data + sizeof(TPacketCGWhisper), MIN(iExtraLen + 1, sizeof(buf)));
  414.             const size_t buflen = strlen(buf);
  415.  
  416.             if (true == SpamBlockCheck(ch, buf, buflen))
  417.             {
  418.                 if (!pkChr)
  419.                 {
  420.                     CCI * pkCCI = P2P_MANAGER::instance().Find(pinfo->szNameTo);
  421.  
  422.                     if (pkCCI)
  423.                     {
  424.                         pkDesc->SetRelay("");
  425.                     }
  426.                 }
  427.                 return iExtraLen;
  428.             }
  429.  
  430.             CBanwordManager::instance().ConvertString(buf, buflen);
  431.  
  432.             if (g_bEmpireWhisper)
  433.                 if (!ch->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
  434.                     if (!(pkChr && pkChr->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE)))
  435.                         if (bOpponentEmpire != ch->GetEmpire() && ch->GetEmpire() && bOpponentEmpire // ¼­·Î Á¦±¹ÀÌ ´Ù¸£¸é¼­
  436.                                 && ch->GetGMLevel() == GM_PLAYER && gm_get_level(pinfo->szNameTo) == GM_PLAYER) // µÑ´Ù ÀÏ¹Ý Ç÷¹À̾îÀ̸é
  437.                             // À̸§ ¹Û¿¡ ¸ð¸£´Ï gm_get_level ÇÔ¼ö¸¦ »ç¿ë
  438.                         {
  439.                             if (!pkChr)
  440.                             {
  441.                                 // ´Ù¸¥ ¼­¹ö¿¡ ÀÖÀ¸´Ï Á¦±¹ Ç¥½Ã¸¸ ÇÑ´Ù. bTypeÀÇ »óÀ§ 4ºñÆ®¸¦ Empire¹øÈ£·Î »ç¿ëÇÑ´Ù.
  442.                                 bType = ch->GetEmpire() << 4;
  443.                             }
  444.                             else
  445.                             {
  446.                                 ConvertEmpireText(ch->GetEmpire(), buf, buflen, 10 + 2 * pkChr->GetSkillPower(SKILL_LANGUAGE1 + ch->GetEmpire() - 1)/*º¯È¯È®·ü*/);
  447.                             }
  448.                         }
  449.  
  450.             int processReturn = ProcessTextTag(ch, buf, buflen);
  451.             if (0!=processReturn)
  452.             {
  453.                 if (ch->GetDesc())
  454.                 {
  455.                     TItemTable * pTable = ITEM_MANAGER::instance().GetTable(ITEM_PRISM);
  456.  
  457.                     if (pTable)
  458.                     {
  459.                         char buf[128];
  460.                         int len;
  461.                         if (3==processReturn) //±³È¯Áß
  462.                             len = snprintf(buf, sizeof(buf), LC_TEXT("»ç¿ëÇÒ¼ö ¾ø½À´Ï´Ù."), pTable->szLocaleName);
  463.                         else
  464.                             len = snprintf(buf, sizeof(buf), LC_TEXT("%sÀÌ ÇÊ¿äÇÕ´Ï´Ù."), pTable->szLocaleName);
  465.  
  466.                         if (len < 0 || len >= (int) sizeof(buf))
  467.                             len = sizeof(buf) - 1;
  468.  
  469.                         ++len;  // \0 ¹®ÀÚ Æ÷ÇÔ
  470.  
  471.                         TPacketGCWhisper pack;
  472.  
  473.                         pack.bHeader = HEADER_GC_WHISPER;
  474.                         pack.bType = WHISPER_TYPE_ERROR;
  475.                         pack.wSize = sizeof(TPacketGCWhisper) + len;
  476.                         strlcpy(pack.szNameFrom, pinfo->szNameTo, sizeof(pack.szNameFrom));
  477.  
  478.                         ch->GetDesc()->BufferedPacket(&pack, sizeof(pack));
  479.                         ch->GetDesc()->Packet(buf, len);
  480.  
  481.                         sys_log(0, "WHISPER: not enough %s: char: %s", pTable->szLocaleName, ch->GetName());
  482.                     }
  483.                 }
  484.  
  485.                 // ¸±·¡ÀÌ »óÅÂÀÏ ¼ö ÀÖÀ¸¹Ç·Î ¸±·¡À̸¦ Ç®¾îÁØ´Ù.
  486.                 pkDesc->SetRelay("");
  487.                 return (iExtraLen);
  488.             }
  489.  
  490.             if (ch->IsGM())
  491.                 bType = (bType & 0xF0) | WHISPER_TYPE_GM;
  492.  
  493.             if (buflen > 0)
  494.             {
  495.                 TPacketGCWhisper pack;
  496.  
  497.                 pack.bHeader = HEADER_GC_WHISPER;
  498.                 pack.wSize = sizeof(TPacketGCWhisper) + buflen;
  499.                 pack.bType = bType;
  500.                 strlcpy(pack.szNameFrom, ch->GetName(), sizeof(pack.szNameFrom));
  501.  
  502.                 // desc->BufferedPacketÀ» ÇÏÁö ¾Ê°í ¹öÆÛ¿¡ ½á¾ßÇÏ´Â ÀÌÀ¯´Â
  503.                 // P2P relayµÇ¾î ÆÐŶÀÌ Ä¸½¶È­ µÉ ¼ö Àֱ⠶§¹®ÀÌ´Ù.
  504.                 TEMP_BUFFER tmpbuf;
  505.  
  506.                 tmpbuf.write(&pack, sizeof(pack));
  507.                 tmpbuf.write(buf, buflen);
  508.  
  509.                 pkDesc->Packet(tmpbuf.read_peek(), tmpbuf.size());
  510.  
  511.                 // @warme006
  512.                 // sys_log(0, "WHISPER: %s -> %s : %s", ch->GetName(), pinfo->szNameTo, buf);
  513. #ifdef ENABLE_CHAT_LOGGING
  514.                 if (ch->IsGM())
  515.                 {
  516.                     LogManager::instance().EscapeString(__escape_string, sizeof(__escape_string), buf, buflen);
  517.                     LogManager::instance().EscapeString(__escape_string2, sizeof(__escape_string2), pinfo->szNameTo, sizeof(pack.szNameFrom));
  518.                     LogManager::instance().ChatLog(ch->GetMapIndex(), ch->GetPlayerID(), ch->GetName(), 0, __escape_string2, "WHISPER", __escape_string, ch->GetDesc() ? ch->GetDesc()->GetHostName() : "");
  519.                 }
  520. #endif
  521.             }
  522.         }
  523.     }
  524.     if(pkDesc)
  525.         pkDesc->SetRelay("");
  526.  
  527.     return (iExtraLen);
  528. }
  529.  
  530. struct RawPacketToCharacterFunc
  531. {
  532.     const void * m_buf;
  533.     int m_buf_len;
  534.  
  535.     RawPacketToCharacterFunc(const void * buf, int buf_len) : m_buf(buf), m_buf_len(buf_len)
  536.     {
  537.     }
  538.  
  539.     void operator () (LPCHARACTER c)
  540.     {
  541.         if (!c->GetDesc())
  542.             return;
  543.  
  544.         c->GetDesc()->Packet(m_buf, m_buf_len);
  545.     }
  546. };
  547.  
  548. struct FEmpireChatPacket
  549. {
  550.     packet_chat& p;
  551.     const char* orig_msg;
  552.     int orig_len;
  553.     char converted_msg[CHAT_MAX_LEN+1];
  554.  
  555.     BYTE bEmpire;
  556.     int iMapIndex;
  557.     int namelen;
  558.  
  559.     FEmpireChatPacket(packet_chat& p, const char* chat_msg, int len, BYTE bEmpire, int iMapIndex, int iNameLen)
  560.         : p(p), orig_msg(chat_msg), orig_len(len), bEmpire(bEmpire), iMapIndex(iMapIndex), namelen(iNameLen)
  561.     {
  562.         memset( converted_msg, 0, sizeof(converted_msg) );
  563.     }
  564.  
  565.     void operator () (LPDESC d)
  566.     {
  567.         if (!d->GetCharacter())
  568.             return;
  569.  
  570.         if (d->GetCharacter()->GetMapIndex() != iMapIndex)
  571.             return;
  572.  
  573.         d->BufferedPacket(&p, sizeof(packet_chat));
  574.  
  575.         if (d->GetEmpire() == bEmpire ||
  576.             bEmpire == 0 ||
  577.             d->GetCharacter()->GetGMLevel() > GM_PLAYER ||
  578.             d->GetCharacter()->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
  579.         {
  580.             d->Packet(orig_msg, orig_len);
  581.         }
  582.         else
  583.         {
  584.             // »ç¶÷¸¶´Ù ½ºÅ³·¹º§ÀÌ ´Ù¸£´Ï ¸Å¹ø ÇØ¾ßÇÕ´Ï´Ù
  585.             size_t len = strlcpy(converted_msg, orig_msg, sizeof(converted_msg));
  586.  
  587.             if (len >= sizeof(converted_msg))
  588.                 len = sizeof(converted_msg) - 1;
  589.  
  590.             ConvertEmpireText(bEmpire, converted_msg + namelen, len - namelen, 10 + 2 * d->GetCharacter()->GetSkillPower(SKILL_LANGUAGE1 + bEmpire - 1));
  591.             d->Packet(converted_msg, orig_len);
  592.         }
  593.     }
  594. };
  595.  
  596. struct FYmirChatPacket
  597. {
  598.     packet_chat& packet;
  599.     const char* m_szChat;
  600.     size_t m_lenChat;
  601.     const char* m_szName;
  602.  
  603.     int m_iMapIndex;
  604.     BYTE m_bEmpire;
  605.     bool m_ring;
  606.  
  607.     char m_orig_msg[CHAT_MAX_LEN+1];
  608.     int m_len_orig_msg;
  609.     char m_conv_msg[CHAT_MAX_LEN+1];
  610.     int m_len_conv_msg;
  611.  
  612.     FYmirChatPacket(packet_chat& p, const char* chat, size_t len_chat, const char* name, size_t len_name, int iMapIndex, BYTE empire, bool ring)
  613.         : packet(p),
  614.         m_szChat(chat), m_lenChat(len_chat),
  615.         m_szName(name),
  616.         m_iMapIndex(iMapIndex), m_bEmpire(empire),
  617.         m_ring(ring)
  618.     {
  619.         m_len_orig_msg = snprintf(m_orig_msg, sizeof(m_orig_msg), "%s : %s", m_szName, m_szChat) + 1; // ³Î ¹®ÀÚ Æ÷ÇÔ
  620.  
  621.         if (m_len_orig_msg < 0 || m_len_orig_msg >= (int) sizeof(m_orig_msg))
  622.             m_len_orig_msg = sizeof(m_orig_msg) - 1;
  623.  
  624.         m_len_conv_msg = snprintf(m_conv_msg, sizeof(m_conv_msg), "??? : %s", m_szChat) + 1; // ³Î ¹®ÀÚ ¹ÌÆ÷ÇÔ
  625.  
  626.         if (m_len_conv_msg < 0 || m_len_conv_msg >= (int) sizeof(m_conv_msg))
  627.             m_len_conv_msg = sizeof(m_conv_msg) - 1;
  628.  
  629.         ConvertEmpireText(m_bEmpire, m_conv_msg + 6, m_len_conv_msg - 6, 10); // 6Àº "??? : "ÀÇ ±æÀÌ
  630.     }
  631.  
  632.     void operator() (LPDESC d)
  633.     {
  634.         if (!d->GetCharacter())
  635.             return;
  636.  
  637.         if (d->GetCharacter()->GetMapIndex() != m_iMapIndex)
  638.             return;
  639.  
  640.         if (m_ring ||
  641.             d->GetEmpire() == m_bEmpire ||
  642.             d->GetCharacter()->GetGMLevel() > GM_PLAYER ||
  643.             d->GetCharacter()->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE))
  644.         {
  645.             packet.size = m_len_orig_msg + sizeof(TPacketGCChat);
  646.  
  647.             d->BufferedPacket(&packet, sizeof(packet_chat));
  648.             d->Packet(m_orig_msg, m_len_orig_msg);
  649.         }
  650.         else
  651.         {
  652.             packet.size = m_len_conv_msg + sizeof(TPacketGCChat);
  653.  
  654.             d->BufferedPacket(&packet, sizeof(packet_chat));
  655.             d->Packet(m_conv_msg, m_len_conv_msg);
  656.         }
  657.     }
  658. };
  659.  
  660. int CInputMain::Chat(LPCHARACTER ch, const char * data, size_t uiBytes)
  661. {
  662.     const TPacketCGChat* pinfo = reinterpret_cast<const TPacketCGChat*>(data);
  663.  
  664.     if (uiBytes < pinfo->size)
  665.         return -1;
  666.  
  667.     const int iExtraLen = pinfo->size - sizeof(TPacketCGChat);
  668.  
  669.     if (iExtraLen < 0)
  670.     {
  671.         sys_err("invalid packet length (len %d size %u buffer %u)", iExtraLen, pinfo->size, uiBytes);
  672.         ch->GetDesc()->SetPhase(PHASE_CLOSE);
  673.         return -1;
  674.     }
  675.  
  676.     char buf[CHAT_MAX_LEN - (CHARACTER_NAME_MAX_LEN + 3) + 1];
  677.     strlcpy(buf, data + sizeof(TPacketCGChat), MIN(iExtraLen + 1, sizeof(buf)));
  678.     const size_t buflen = strlen(buf);
  679.  
  680.     if (buflen > 1 && *buf == '/')
  681.     {
  682.         interpret_command(ch, buf + 1, buflen - 1);
  683.         return iExtraLen;
  684.     }
  685. #ifdef ENABLE_CHAT_SPAMLIMIT
  686.     if (ch->IncreaseChatCounter() >= 4)
  687.     {
  688.         if (ch->GetChatCounter() == 10)
  689.             ch->GetDesc()->DelayedDisconnect(0);
  690.         return iExtraLen;
  691.     }
  692. #else
  693.     if (ch->IncreaseChatCounter() >= 10)
  694.     {
  695.         if (ch->GetChatCounter() == 10)
  696.         {
  697.             sys_log(0, "CHAT_HACK: %s", ch->GetName());
  698.             ch->GetDesc()->DelayedDisconnect(5);
  699.         }
  700.  
  701.         return iExtraLen;
  702.     }
  703. #endif
  704.  
  705.     // äÆÃ ±ÝÁö Affect ó¸®
  706.     const CAffect* pAffect = ch->FindAffect(AFFECT_BLOCK_CHAT);
  707.  
  708.     if (pAffect != NULL)
  709.     {
  710.         SendBlockChatInfo(ch, pAffect->lDuration);
  711.         return iExtraLen;
  712.     }
  713.  
  714.     if (true == SpamBlockCheck(ch, buf, buflen))
  715.     {
  716.         return iExtraLen;
  717.     }
  718.  
  719.     // @fixme133 begin
  720.     CBanwordManager::instance().ConvertString(buf, buflen);
  721.  
  722.     int processReturn = ProcessTextTag(ch, buf, buflen);
  723.     if (0!=processReturn)
  724.     {
  725.         const TItemTable* pTable = ITEM_MANAGER::instance().GetTable(ITEM_PRISM);
  726.  
  727.         if (NULL != pTable)
  728.         {
  729.             if (3==processReturn) //±³È¯Áß
  730.                 ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ç¿ëÇÒ¼ö ¾ø½À´Ï´Ù."), pTable->szLocaleName);
  731.             else
  732.                 ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%sÀÌ ÇÊ¿äÇÕ´Ï´Ù."), pTable->szLocaleName);
  733.  
  734.         }
  735.  
  736.         return iExtraLen;
  737.     }
  738.     // @fixme133 end
  739.  
  740.     char chatbuf[CHAT_MAX_LEN + 1];
  741. #ifdef ENABLE_CHAT_COLOR_SYSTEM
  742.     // static const char* colorbuf[] = {" |h|r[ãÑÇÞÈ]|cFFffa200|h", " |h|r[ÔíäÓæ]|cFFff0000|h", " |h|r[ÔæäÌæ]|cFFffc700|h", " |h|r[Ìíäæ]|cFF000bff|h"}; // Arab
  743.     static const char* colorbuf[] = {"|cFFffa200|H|h[Staff]|h|r", "|cFFff0000|H|h[Shinsoo]|h|r", "|cFFffc700|H|h[Chunjo]|h|r", "|cFF000bff|H|h[Jinno]|h|r"};
  744.     int len = snprintf(chatbuf, sizeof(chatbuf), "%s %s : %s", (ch->IsGM()?colorbuf[0]:colorbuf[MINMAX(0, ch->GetEmpire(), 3)]), ch->GetName(), buf);
  745. #else
  746.     int len = snprintf(chatbuf, sizeof(chatbuf), "%s : %s", ch->GetName(), buf);
  747. #endif
  748.     if (CHAT_TYPE_SHOUT == pinfo->type)
  749.     {
  750.         LogManager::instance().ShoutLog(g_bChannel, ch->GetEmpire(), chatbuf);
  751.     }
  752.  
  753.     if (len < 0 || len >= (int) sizeof(chatbuf))
  754.         len = sizeof(chatbuf) - 1;
  755.  
  756.     if (pinfo->type == CHAT_TYPE_SHOUT)
  757.     {
  758.         // const int SHOUT_LIMIT_LEVEL = 15;
  759.  
  760.         if (ch->GetLevel() < g_iShoutLimitLevel)
  761.         {
  762.             ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¿ÜÄ¡±â´Â ·¹º§ %d ÀÌ»ó¸¸ »ç¿ë °¡´É ÇÕ´Ï´Ù."), g_iShoutLimitLevel);
  763.             return (iExtraLen);
  764.         }
  765.  
  766.         // if (thecore_heart->pulse - (int) ch->GetLastShoutPulse() < passes_per_sec * g_iShoutLimitTime)
  767.         if (thecore_heart->pulse - (int) ch->GetLastShoutPulse() < passes_per_sec * 15)
  768.             return (iExtraLen);
  769.  
  770.         ch->SetLastShoutPulse(thecore_heart->pulse);
  771.  
  772.         TPacketGGShout p;
  773.  
  774.         p.bHeader = HEADER_GG_SHOUT;
  775.         p.bEmpire = ch->GetEmpire();
  776.         strlcpy(p.szText, chatbuf, sizeof(p.szText));
  777.  
  778.         P2P_MANAGER::instance().Send(&p, sizeof(TPacketGGShout));
  779.  
  780.         SendShout(chatbuf, ch->GetEmpire());
  781.  
  782.         return (iExtraLen);
  783.     }
  784.  
  785.     TPacketGCChat pack_chat;
  786.  
  787.     pack_chat.header = HEADER_GC_CHAT;
  788.     pack_chat.size = sizeof(TPacketGCChat) + len;
  789.     pack_chat.type = pinfo->type;
  790.     pack_chat.id = ch->GetVID();
  791.  
  792.     switch (pinfo->type)
  793.     {
  794.         case CHAT_TYPE_TALKING:
  795.             {
  796.                 const DESC_MANAGER::DESC_SET & c_ref_set = DESC_MANAGER::instance().GetClientSet();
  797.  
  798.                 if (false)
  799.                 {
  800.                     std::for_each(c_ref_set.begin(), c_ref_set.end(),
  801.                             FYmirChatPacket(pack_chat,
  802.                                 buf,
  803.                                 strlen(buf),
  804.                                 ch->GetName(),
  805.                                 strlen(ch->GetName()),
  806.                                 ch->GetMapIndex(),
  807.                                 ch->GetEmpire(),
  808.                                 ch->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE)));
  809.                 }
  810.                 else
  811.                 {
  812.                     std::for_each(c_ref_set.begin(), c_ref_set.end(),
  813.                             FEmpireChatPacket(pack_chat,
  814.                                 chatbuf,
  815.                                 len,
  816.                                 (ch->GetGMLevel() > GM_PLAYER ||
  817.                                  ch->IsEquipUniqueGroup(UNIQUE_GROUP_RING_OF_LANGUAGE)) ? 0 : ch->GetEmpire(),
  818.                                 ch->GetMapIndex(), strlen(ch->GetName())));
  819. #ifdef ENABLE_CHAT_LOGGING
  820.                     if (ch->IsGM())
  821.                     {
  822.                         LogManager::instance().EscapeString(__escape_string, sizeof(__escape_string), chatbuf, len);
  823.                         LogManager::instance().ChatLog(ch->GetMapIndex(), ch->GetPlayerID(), ch->GetName(), 0, "", "NORMAL", __escape_string, ch->GetDesc() ? ch->GetDesc()->GetHostName() : "");
  824.                     }
  825. #endif
  826.                 }
  827.             }
  828.             break;
  829.  
  830.         case CHAT_TYPE_PARTY:
  831.             {
  832.                 if (!ch->GetParty())
  833.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ÆÄƼ ÁßÀÌ ¾Æ´Õ´Ï´Ù."));
  834.                 else
  835.                 {
  836.                     TEMP_BUFFER tbuf;
  837.  
  838.                     tbuf.write(&pack_chat, sizeof(pack_chat));
  839.                     tbuf.write(chatbuf, len);
  840.  
  841.                     RawPacketToCharacterFunc f(tbuf.read_peek(), tbuf.size());
  842.                     ch->GetParty()->ForEachOnlineMember(f);
  843. #ifdef ENABLE_CHAT_LOGGING
  844.                     if (ch->IsGM())
  845.                     {
  846.                         LogManager::instance().EscapeString(__escape_string, sizeof(__escape_string), chatbuf, len);
  847.                         LogManager::instance().ChatLog(ch->GetMapIndex(), ch->GetPlayerID(), ch->GetName(), ch->GetParty()->GetLeaderPID(), "", "PARTY", __escape_string, ch->GetDesc() ? ch->GetDesc()->GetHostName() : "");
  848.                     }
  849. #endif
  850.                 }
  851.             }
  852.             break;
  853.  
  854.         case CHAT_TYPE_GUILD:
  855.             {
  856.                 if (!ch->GetGuild())
  857.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("±æµå¿¡ °¡ÀÔÇÏÁö ¾Ê¾Ò½À´Ï´Ù."));
  858.                 else
  859.                 {
  860.                     ch->GetGuild()->Chat(chatbuf);
  861. #ifdef ENABLE_CHAT_LOGGING
  862.                     if (ch->IsGM())
  863.                     {
  864.                         LogManager::instance().EscapeString(__escape_string, sizeof(__escape_string), chatbuf, len);
  865.                         LogManager::instance().ChatLog(ch->GetMapIndex(), ch->GetPlayerID(), ch->GetName(), ch->GetGuild()->GetID(), ch->GetGuild()->GetName(), "GUILD", __escape_string, ch->GetDesc() ? ch->GetDesc()->GetHostName() : "");
  866.                     }
  867. #endif
  868.                 }
  869.             }
  870.             break;
  871.  
  872.         default:
  873.             sys_err("Unknown chat type %d", pinfo->type);
  874.             break;
  875.     }
  876.  
  877.     return (iExtraLen);
  878. }
  879.  
  880. void CInputMain::ItemUse(LPCHARACTER ch, const char * data)
  881. {
  882.     ch->UseItem(((struct command_item_use *) data)->Cell);
  883. }
  884.  
  885. void CInputMain::ItemToItem(LPCHARACTER ch, const char * pcData)
  886. {
  887.     TPacketCGItemUseToItem * p = (TPacketCGItemUseToItem *) pcData;
  888.     if (ch)
  889.         ch->UseItem(p->Cell, p->TargetCell);
  890. }
  891.  
  892. void CInputMain::ItemDrop(LPCHARACTER ch, const char * data)
  893. {
  894.     struct command_item_drop * pinfo = (struct command_item_drop *) data;
  895.  
  896.     //MONARCH_LIMIT
  897.     //if (ch->IsMonarch())
  898.     //  return;
  899.     //END_MONARCH_LIMIT
  900.     if (!ch)
  901.         return;
  902.  
  903.     // ¿¤Å©°¡ 0º¸´Ù Å©¸é ¿¤Å©¸¦ ¹ö¸®´Â °Í ÀÌ´Ù.
  904.     if (pinfo->gold > 0)
  905.         ch->DropGold(pinfo->gold);
  906.     else
  907.         ch->DropItem(pinfo->Cell);
  908. }
  909.  
  910. void CInputMain::ItemDrop2(LPCHARACTER ch, const char * data)
  911. {
  912.     //MONARCH_LIMIT
  913.     //if (ch->IsMonarch())
  914.     //  return;
  915.     //END_MONARCH_LIMIT
  916.  
  917.     TPacketCGItemDrop2 * pinfo = (TPacketCGItemDrop2 *) data;
  918.  
  919.     // ¿¤Å©°¡ 0º¸´Ù Å©¸é ¿¤Å©¸¦ ¹ö¸®´Â °Í ÀÌ´Ù.
  920.  
  921.     if (!ch)
  922.         return;
  923.     if (pinfo->gold > 0)
  924.         ch->DropGold(pinfo->gold);
  925.     else
  926.         ch->DropItem(pinfo->Cell, pinfo->count);
  927. }
  928.  
  929. void CInputMain::ItemMove(LPCHARACTER ch, const char * data)
  930. {
  931.     struct command_item_move * pinfo = (struct command_item_move *) data;
  932.  
  933.     if (ch)
  934.         ch->MoveItem(pinfo->Cell, pinfo->CellTo, pinfo->count);
  935. }
  936.  
  937. void CInputMain::ItemPickup(LPCHARACTER ch, const char * data)
  938. {
  939.     struct command_item_pickup * pinfo = (struct command_item_pickup*) data;
  940.     if (ch)
  941.         ch->PickupItem(pinfo->vid);
  942. }
  943.  
  944. void CInputMain::QuickslotAdd(LPCHARACTER ch, const char * data)
  945. {
  946.     struct command_quickslot_add * pinfo = (struct command_quickslot_add *) data;
  947.     ch->SetQuickslot(pinfo->pos, pinfo->slot);
  948. }
  949.  
  950. void CInputMain::QuickslotDelete(LPCHARACTER ch, const char * data)
  951. {
  952.     struct command_quickslot_del * pinfo = (struct command_quickslot_del *) data;
  953.     ch->DelQuickslot(pinfo->pos);
  954. }
  955.  
  956. void CInputMain::QuickslotSwap(LPCHARACTER ch, const char * data)
  957. {
  958.     struct command_quickslot_swap * pinfo = (struct command_quickslot_swap *) data;
  959.     ch->SwapQuickslot(pinfo->pos, pinfo->change_pos);
  960. }
  961.  
  962. int CInputMain::Messenger(LPCHARACTER ch, const char* c_pData, size_t uiBytes)
  963. {
  964.     TPacketCGMessenger* p = (TPacketCGMessenger*) c_pData;
  965.  
  966.     if (uiBytes < sizeof(TPacketCGMessenger))
  967.         return -1;
  968.  
  969.     c_pData += sizeof(TPacketCGMessenger);
  970.     uiBytes -= sizeof(TPacketCGMessenger);
  971.  
  972.     switch (p->subheader)
  973.     {
  974.         case MESSENGER_SUBHEADER_CG_ADD_BY_VID:
  975.             {
  976.                 if (uiBytes < sizeof(TPacketCGMessengerAddByVID))
  977.                     return -1;
  978.  
  979.                 TPacketCGMessengerAddByVID * p2 = (TPacketCGMessengerAddByVID *) c_pData;
  980.                 LPCHARACTER ch_companion = CHARACTER_MANAGER::instance().Find(p2->vid);
  981.  
  982.                 if (!ch_companion)
  983.                     return sizeof(TPacketCGMessengerAddByVID);
  984.  
  985.                 if (ch->IsObserverMode())
  986.                     return sizeof(TPacketCGMessengerAddByVID);
  987.  
  988.                 if (ch_companion->IsBlockMode(BLOCK_MESSENGER_INVITE))
  989.                 {
  990.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ó´ë¹æÀÌ ¸Þ½ÅÁ® Ãß°¡ °ÅºÎ »óÅÂÀÔ´Ï´Ù."));
  991.                     return sizeof(TPacketCGMessengerAddByVID);
  992.                 }
  993.  
  994.                 LPDESC d = ch_companion->GetDesc();
  995.  
  996.                 if (!d)
  997.                     return sizeof(TPacketCGMessengerAddByVID);
  998.  
  999.                 if (ch->GetGMLevel() == GM_PLAYER && ch_companion->GetGMLevel() != GM_PLAYER)
  1000.                 {
  1001.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<¸Þ½ÅÁ®> ¿î¿µÀÚ´Â ¸Þ½ÅÁ®¿¡ Ãß°¡ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  1002.                     return sizeof(TPacketCGMessengerAddByVID);
  1003.                 }
  1004.  
  1005.                 if (ch->GetDesc() == d) // ÀÚ½ÅÀº Ãß°¡ÇÒ ¼ö ¾ø´Ù.
  1006.                     return sizeof(TPacketCGMessengerAddByVID);
  1007.  
  1008.                 MessengerManager::instance().RequestToAdd(ch, ch_companion);
  1009.                 //MessengerManager::instance().AddToList(ch->GetName(), ch_companion->GetName());
  1010.             }
  1011.             return sizeof(TPacketCGMessengerAddByVID);
  1012.  
  1013.         case MESSENGER_SUBHEADER_CG_ADD_BY_NAME:
  1014.             {
  1015.                 if (uiBytes < CHARACTER_NAME_MAX_LEN)
  1016.                     return -1;
  1017.  
  1018.                 char name[CHARACTER_NAME_MAX_LEN + 1];
  1019.                 strlcpy(name, c_pData, sizeof(name));
  1020.  
  1021.                 if (ch->GetGMLevel() == GM_PLAYER && gm_get_level(name) != GM_PLAYER)
  1022.                 {
  1023.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<¸Þ½ÅÁ®> ¿î¿µÀÚ´Â ¸Þ½ÅÁ®¿¡ Ãß°¡ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  1024.                     return CHARACTER_NAME_MAX_LEN;
  1025.                 }
  1026.  
  1027.                 LPCHARACTER tch = CHARACTER_MANAGER::instance().FindPC(name);
  1028.  
  1029.                 if (!tch)
  1030.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s ´ÔÀº Á¢¼ÓµÇ ÀÖÁö ¾Ê½À´Ï´Ù."), name);
  1031.                 else
  1032.                 {
  1033.                     if (tch == ch) // ÀÚ½ÅÀº Ãß°¡ÇÒ ¼ö ¾ø´Ù.
  1034.                         return CHARACTER_NAME_MAX_LEN;
  1035.  
  1036.                     if (tch->IsBlockMode(BLOCK_MESSENGER_INVITE) == true)
  1037.                     {
  1038.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ó´ë¹æÀÌ ¸Þ½ÅÁ® Ãß°¡ °ÅºÎ »óÅÂÀÔ´Ï´Ù."));
  1039.                     }
  1040.                     else
  1041.                     {
  1042.                         // ¸Þ½ÅÀú°¡ ij¸¯ÅÍ´ÜÀ§°¡ µÇ¸é¼­ º¯°æ
  1043.                         MessengerManager::instance().RequestToAdd(ch, tch);
  1044.                         //MessengerManager::instance().AddToList(ch->GetName(), tch->GetName());
  1045.                     }
  1046.                 }
  1047.             }
  1048.             return CHARACTER_NAME_MAX_LEN;
  1049.  
  1050.         case MESSENGER_SUBHEADER_CG_REMOVE:
  1051.             {
  1052.                 if (uiBytes < CHARACTER_NAME_MAX_LEN)
  1053.                     return -1;
  1054.  
  1055.                 char char_name[CHARACTER_NAME_MAX_LEN + 1];
  1056.                 strlcpy(char_name, c_pData, sizeof(char_name));
  1057.                 MessengerManager::instance().RemoveFromList(ch->GetName(), char_name);
  1058.             }
  1059.             return CHARACTER_NAME_MAX_LEN;
  1060.  
  1061.         default:
  1062.             sys_err("CInputMain::Messenger : Unknown subheader %d : %s", p->subheader, ch->GetName());
  1063.             break;
  1064.     }
  1065.  
  1066.     return 0;
  1067. }
  1068.  
  1069. int CInputMain::Shop(LPCHARACTER ch, const char * data, size_t uiBytes)
  1070. {
  1071.     TPacketCGShop * p = (TPacketCGShop *) data;
  1072.  
  1073.     if (uiBytes < sizeof(TPacketCGShop))
  1074.         return -1;
  1075.  
  1076.     if (test_server)
  1077.         sys_log(0, "CInputMain::Shop() ==> SubHeader %d", p->subheader);
  1078.  
  1079.     const char * c_pData = data + sizeof(TPacketCGShop);
  1080.     uiBytes -= sizeof(TPacketCGShop);
  1081.  
  1082.     switch (p->subheader)
  1083.     {
  1084.         case SHOP_SUBHEADER_CG_END:
  1085.             sys_log(1, "INPUT: %s SHOP: END", ch->GetName());
  1086.             CShopManager::instance().StopShopping(ch);
  1087.             return 0;
  1088.  
  1089.         case SHOP_SUBHEADER_CG_BUY:
  1090.             {
  1091.                 if (uiBytes < sizeof(BYTE) + sizeof(BYTE))
  1092.                     return -1;
  1093.  
  1094.                 BYTE bPos = *(c_pData + 1);
  1095.                 sys_log(1, "INPUT: %s SHOP: BUY %d", ch->GetName(), bPos);
  1096.                 CShopManager::instance().Buy(ch, bPos);
  1097.                 return (sizeof(BYTE) + sizeof(BYTE));
  1098.             }
  1099.  
  1100.         case SHOP_SUBHEADER_CG_SELL:
  1101.             {
  1102.                 if (uiBytes < sizeof(BYTE))
  1103.                     return -1;
  1104.  
  1105.                 BYTE pos = *c_pData;
  1106.  
  1107.                 sys_log(0, "INPUT: %s SHOP: SELL", ch->GetName());
  1108.                 CShopManager::instance().Sell(ch, pos);
  1109.                 return sizeof(BYTE);
  1110.             }
  1111.  
  1112.         case SHOP_SUBHEADER_CG_SELL2:
  1113.             {
  1114.                 if (uiBytes < sizeof(BYTE) + sizeof(BYTE))
  1115.                     return -1;
  1116.  
  1117.                 BYTE pos = *(c_pData++);
  1118.                 BYTE count = *(c_pData);
  1119.  
  1120.                 sys_log(0, "INPUT: %s SHOP: SELL2", ch->GetName());
  1121.                 CShopManager::instance().Sell(ch, pos, count);
  1122.                 return sizeof(BYTE) + sizeof(BYTE);
  1123.             }
  1124.  
  1125.         default:
  1126.             sys_err("CInputMain::Shop : Unknown subheader %d : %s", p->subheader, ch->GetName());
  1127.             break;
  1128.     }
  1129.  
  1130.     return 0;
  1131. }
  1132.  
  1133. int CInputMain::OfflineShop(LPCHARACTER ch, const char * data, size_t uiBytes)
  1134. {
  1135.     TPacketCGShop * p = (TPacketCGShop *)data;
  1136.  
  1137.     if (uiBytes < sizeof(TPacketCGShop))
  1138.         return -1;
  1139.  
  1140.     if (test_server)
  1141.         sys_log(0, "CInputMain::OfflineShop ==> SubHeader %d", p->subheader);
  1142.  
  1143.     const char * c_pData = data + sizeof(TPacketCGShop);
  1144.     uiBytes -= sizeof(TPacketCGShop);
  1145.  
  1146.     switch (p->subheader)
  1147.     {
  1148.         case SHOP_SUBHEADER_CG_END:
  1149.             sys_log(1, "INPUT: %s OFFLINE_SHOP: END", ch->GetName());
  1150.             COfflineShopManager::instance().StopShopping(ch);
  1151.             return 0;
  1152.         case SHOP_SUBHEADER_CG_BUY:
  1153.         {
  1154.             if (uiBytes < sizeof(BYTE) + sizeof(BYTE))
  1155.                 return -1;
  1156.  
  1157.             BYTE bPos = *(c_pData + 1);
  1158.             sys_log(1, "INPUT: %s OFFLINE_SHOP: BUY %d", ch->GetName(), bPos);
  1159.             COfflineShopManager::instance().Buy(ch, bPos);
  1160.             return (sizeof(BYTE) + sizeof(BYTE));
  1161.         }
  1162.         case SHOP_SUBHEADER_CG_CHANGE_EDIT_TIME:
  1163.         {
  1164.             if (uiBytes < sizeof(BYTE))
  1165.                 return -1;
  1166.  
  1167.             BYTE bTime = *c_pData;
  1168.             sys_log(0, "INPUT: %s EDIT_OFFLINE_SHOP_TIME", ch->GetName());
  1169.             COfflineShopManager::instance().ChangeOfflineShopTime(ch, bTime);
  1170.             return sizeof(BYTE);
  1171.         }
  1172.         case SHOP_SUBHEADER_CG_DESTROY_OFFLINE_SHOP:
  1173.             sys_log(1, "INPUT: %s OFFLINE_SHOP_DESTROY", ch->GetName());
  1174.             COfflineShopManager::instance().DestroyOfflineShop(ch, ch->GetOfflineShopVID(), true);
  1175.             return 0;
  1176.         case SHOP_SUBHEADER_CG_ADD_ITEM:
  1177.         {
  1178.             if (uiBytes < sizeof(TOfflineShopItemTable))
  1179.                 return -1;
  1180.  
  1181.             TOfflineShopItemTable * pTable = (TOfflineShopItemTable *)(c_pData);
  1182.             COfflineShopManager::instance().AddItem(ch, pTable->bDisplayPos, pTable->bPos, pTable->lPrice);
  1183.             return (sizeof(TOfflineShopItemTable));
  1184.         }
  1185.         case SHOP_SUBHEADER_CG_REMOVE_ITEM:
  1186.         {
  1187.             if (uiBytes < sizeof(BYTE))
  1188.                 return -1;
  1189.  
  1190.             BYTE bPos = *c_pData;
  1191.             sys_log(0, "INPUT: %s REMOVE_ITEM : %d", ch->GetName(), bPos);
  1192.             COfflineShopManager::instance().RemoveItem(ch, bPos);
  1193.             return (sizeof(BYTE));
  1194.         }
  1195.         case SHOP_SUBHEADER_CG_CHANGE_PRICE:
  1196.         {
  1197.             if (uiBytes < sizeof(TOfflineShopItemTable))
  1198.                 return -1;
  1199.                    
  1200.             TOfflineShopItemTable * pTable = (TOfflineShopItemTable *)(c_pData);
  1201.             sys_log(0, "INPUT: %s OFFLINE_CHANGE_PRICE (%d)", ch->GetName(), pTable->bPos);
  1202.             COfflineShopManager::instance().ChangePrice(ch, pTable->bPos, pTable->lPrice);
  1203.             return (sizeof(TOfflineShopItemTable));
  1204.         }
  1205.         case SHOP_SUBHEADER_CG_REFRESH:
  1206.             sys_log(0, "INPUT: %s OFFLINE_SHOP_REFRESH_ITEM", ch->GetName());
  1207.             COfflineShopManager::instance().Refresh(ch);
  1208.             return 0;
  1209.         case SHOP_SUBHEADER_CG_REFRESH_MONEY:
  1210.         {
  1211.             sys_log(0, "INPUT: %s OFFLINE_SHOP_REFRESH_MONEY", ch->GetName());
  1212.             COfflineShopManager::instance().RefreshMoney(ch);
  1213.             return 0;
  1214.         }
  1215.         case SHOP_SUBHEADER_CG_WITHDRAW_MONEY:
  1216.         {
  1217.             if (uiBytes < sizeof(DWORD))
  1218.                 return -1;
  1219.  
  1220.             const int gold = *reinterpret_cast<const int*>(c_pData);       
  1221.             sys_log(0, "INPUT: %s(%u) OFFLINE_SHOP_WITHDRAW_MONEY", ch->GetName(), gold);  
  1222.             COfflineShopManager::instance().WithdrawMoney(ch, gold);
  1223.             return (sizeof(DWORD));
  1224.         }
  1225.         default:
  1226.             sys_err("CInputMain::OfflineShop : Unknown subheader %d : %s", p->subheader, ch->GetName());
  1227.             break;
  1228.     }
  1229.  
  1230.     return 0;
  1231. }
  1232.  
  1233. void CInputMain::OnClick(LPCHARACTER ch, const char * data)
  1234. {
  1235.     struct command_on_click *   pinfo = (struct command_on_click *) data;
  1236.     LPCHARACTER         victim;
  1237.  
  1238.     if ((victim = CHARACTER_MANAGER::instance().Find(pinfo->vid)))
  1239.         victim->OnClick(ch);
  1240.     else if (test_server)
  1241.     {
  1242.         sys_err("CInputMain::OnClick %s.Click.NOT_EXIST_VID[%d]", ch->GetName(), pinfo->vid);
  1243.     }
  1244. }
  1245.  
  1246. void CInputMain::Exchange(LPCHARACTER ch, const char * data)
  1247. {
  1248.     struct command_exchange * pinfo = (struct command_exchange *) data;
  1249.     LPCHARACTER to_ch = NULL;
  1250.  
  1251.     if (!ch->CanHandleItem())
  1252.         return;
  1253.  
  1254.     int iPulse = thecore_pulse();
  1255.  
  1256.     if ((to_ch = CHARACTER_MANAGER::instance().Find(pinfo->arg1)))
  1257.     {
  1258.         if (iPulse - to_ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
  1259.         {
  1260.             to_ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°Å·¡ ÈÄ %dÃÊ À̳»¿¡ â°í¸¦ ¿­¼ö ¾ø½À´Ï´Ù."), g_nPortalLimitTime);
  1261.             return;
  1262.         }
  1263.  
  1264.         if( true == to_ch->IsDead() )
  1265.         {
  1266.             return;
  1267.         }
  1268.     }
  1269.  
  1270.     sys_log(0, "CInputMain()::Exchange()  SubHeader %d ", pinfo->sub_header);
  1271.  
  1272.     if (iPulse - ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
  1273.     {
  1274.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°Å·¡ ÈÄ %dÃÊ À̳»¿¡ â°í¸¦ ¿­¼ö ¾ø½À´Ï´Ù."), g_nPortalLimitTime);
  1275.         return;
  1276.     }
  1277.  
  1278.  
  1279.     switch (pinfo->sub_header)
  1280.     {
  1281.         case EXCHANGE_SUBHEADER_CG_START:   // arg1 == vid of target character
  1282.             if (!ch->GetExchange())
  1283.             {
  1284.                 if ((to_ch = CHARACTER_MANAGER::instance().Find(pinfo->arg1)))
  1285.                 {
  1286.                     //MONARCH_LIMIT
  1287.                     /*
  1288.                     if (to_ch->IsMonarch() || ch->IsMonarch())
  1289.                     {
  1290.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("±ºÁÖ¿Í´Â °Å·¡¸¦ ÇÒ¼ö°¡ ¾ø½À´Ï´Ù"), g_nPortalLimitTime);
  1291.                         return;
  1292.                     }
  1293.                     //END_MONARCH_LIMIT
  1294.                     */
  1295.                     if (iPulse - ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
  1296.                     {
  1297.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("â°í¸¦ ¿¬ÈÄ %dÃÊ À̳»¿¡´Â °Å·¡¸¦ ÇÒ¼ö ¾ø½À´Ï´Ù."), g_nPortalLimitTime);
  1298.  
  1299.                         if (test_server)
  1300.                             ch->ChatPacket(CHAT_TYPE_INFO, "[TestOnly][Safebox]Pulse %d LoadTime %d PASS %d", iPulse, ch->GetSafeboxLoadTime(), PASSES_PER_SEC(g_nPortalLimitTime));
  1301.                         return;
  1302.                     }
  1303.  
  1304.                     if (iPulse - to_ch->GetSafeboxLoadTime() < PASSES_PER_SEC(g_nPortalLimitTime))
  1305.                     {
  1306.                         to_ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("â°í¸¦ ¿¬ÈÄ %dÃÊ À̳»¿¡´Â °Å·¡¸¦ ÇÒ¼ö ¾ø½À´Ï´Ù."), g_nPortalLimitTime);
  1307.  
  1308.  
  1309.                         if (test_server)
  1310.                             to_ch->ChatPacket(CHAT_TYPE_INFO, "[TestOnly][Safebox]Pulse %d LoadTime %d PASS %d", iPulse, to_ch->GetSafeboxLoadTime(), PASSES_PER_SEC(g_nPortalLimitTime));
  1311.                         return;
  1312.                     }
  1313.  
  1314.                     if (ch->GetGold() >= GOLD_MAX)
  1315.                     {  
  1316.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¾×¼ö°¡ 20¾ï ³ÉÀ» ÃʰúÇÏ¿© °Å·¡¸¦ ÇÒ¼ö°¡ ¾ø½À´Ï´Ù.."));
  1317.  
  1318.                         sys_err("[OVERFLOG_GOLD] START (%u) id %u name %s ", ch->GetGold(), ch->GetPlayerID(), ch->GetName());
  1319.                         return;
  1320.                     }
  1321.  
  1322.                     if (to_ch->IsPC())
  1323.                     {
  1324.                         if (quest::CQuestManager::instance().GiveItemToPC(ch->GetPlayerID(), to_ch))
  1325.                         {
  1326.                             sys_log(0, "Exchange canceled by quest %s %s", ch->GetName(), to_ch->GetName());
  1327.                             return;
  1328.                         }
  1329.                     }
  1330.  
  1331. #ifdef ENABLE_OFFLINE_SHOP_SYSTEM
  1332.                     if (ch->GetMyShop() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->IsCubeOpen() || ch->GetOfflineShopOwner())
  1333.                     {
  1334.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´Ù¸¥ °Å·¡ÁßÀϰæ¿ì °³ÀλóÁ¡À» ¿­¼ö°¡ ¾ø½À´Ï´Ù."));
  1335.                         return;
  1336.                     }
  1337. #else
  1338.                     if (ch->GetMyShop() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->IsCubeOpen())
  1339.                     {
  1340.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´Ù¸¥ °Å·¡ÁßÀϰæ¿ì °³ÀλóÁ¡À» ¿­¼ö°¡ ¾ø½À´Ï´Ù."));
  1341.                         return;
  1342.                     }
  1343. #endif
  1344.  
  1345.                     ch->ExchangeStart(to_ch);
  1346.                 }
  1347.             }
  1348.             break;
  1349.  
  1350.         case EXCHANGE_SUBHEADER_CG_ITEM_ADD:    // arg1 == position of item, arg2 == position in exchange window
  1351.             if (ch->GetExchange())
  1352.             {
  1353.                 if (ch->GetExchange()->GetCompany()->GetAcceptStatus() != true)
  1354.                     ch->GetExchange()->AddItem(pinfo->Pos, pinfo->arg2);
  1355.             }
  1356.             break;
  1357.  
  1358.         case EXCHANGE_SUBHEADER_CG_ITEM_DEL:    // arg1 == position of item
  1359.             if (ch->GetExchange())
  1360.             {
  1361.                 if (ch->GetExchange()->GetCompany()->GetAcceptStatus() != true)
  1362.                     ch->GetExchange()->RemoveItem(pinfo->arg1);
  1363.             }
  1364.             break;
  1365.  
  1366.         case EXCHANGE_SUBHEADER_CG_ELK_ADD: // arg1 == amount of gold
  1367.             if (ch->GetExchange())
  1368.             {
  1369.                 const int64_t nTotalGold = static_cast<int64_t>(ch->GetExchange()->GetCompany()->GetOwner()->GetGold()) + static_cast<int64_t>(pinfo->arg1);
  1370.  
  1371.                 if (GOLD_MAX <= nTotalGold)
  1372.                 {
  1373.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("»ó´ë¹æÀÇ Ãѱݾ×ÀÌ 20¾ï ³ÉÀ» ÃʰúÇÏ¿© °Å·¡¸¦ ÇÒ¼ö°¡ ¾ø½À´Ï´Ù.."));
  1374.  
  1375.                     sys_err("[OVERFLOW_GOLD] ELK_ADD (%u) id %u name %s ",
  1376.                             ch->GetExchange()->GetCompany()->GetOwner()->GetGold(),
  1377.                             ch->GetExchange()->GetCompany()->GetOwner()->GetPlayerID(),
  1378.                             ch->GetExchange()->GetCompany()->GetOwner()->GetName());
  1379.  
  1380.                     return;
  1381.                 }
  1382.  
  1383.                 if (ch->GetExchange()->GetCompany()->GetAcceptStatus() != true)
  1384.                     ch->GetExchange()->AddGold(pinfo->arg1);
  1385.             }
  1386.             break;
  1387.  
  1388.         case EXCHANGE_SUBHEADER_CG_ACCEPT:  // arg1 == not used
  1389.             if (ch->GetExchange())
  1390.             {
  1391.                 sys_log(0, "CInputMain()::Exchange() ==> ACCEPT ");
  1392.                 ch->GetExchange()->Accept(true);
  1393.             }
  1394.  
  1395.             break;
  1396.  
  1397.         case EXCHANGE_SUBHEADER_CG_CANCEL:  // arg1 == not used
  1398.             if (ch->GetExchange())
  1399.                 ch->GetExchange()->Cancel();
  1400.             break;
  1401.     }
  1402. }
  1403.  
  1404. void CInputMain::Position(LPCHARACTER ch, const char * data)
  1405. {
  1406.     struct command_position * pinfo = (struct command_position *) data;
  1407.  
  1408.     switch (pinfo->position)
  1409.     {
  1410.         case POSITION_GENERAL:
  1411.             ch->Standup();
  1412.             break;
  1413.  
  1414.         case POSITION_SITTING_CHAIR:
  1415.             ch->Sitdown(0);
  1416.             break;
  1417.  
  1418.         case POSITION_SITTING_GROUND:
  1419.             ch->Sitdown(1);
  1420.             break;
  1421.     }
  1422. }
  1423.  
  1424. static const int ComboSequenceBySkillLevel[3][8] =
  1425. {
  1426.     // 0   1   2   3   4   5   6   7
  1427.     { 14, 15, 16, 17,  0,  0,  0,  0 },
  1428.     { 14, 15, 16, 18, 20,  0,  0,  0 },
  1429.     { 14, 15, 16, 18, 19, 17,  0,  0 },
  1430. };
  1431.  
  1432. #define COMBO_HACK_ALLOWABLE_MS 100
  1433.  
  1434. bool CheckComboHack(LPCHARACTER ch, BYTE bArg, DWORD dwTime, bool CheckSpeedHack)
  1435. {
  1436.     if(!gHackCheckEnable) return false;
  1437.  
  1438.     //  Áװųª ±âÀý »óÅ¿¡¼­´Â °ø°ÝÇÒ ¼ö ¾øÀ¸¹Ç·Î, skipÇÑ´Ù.
  1439.     //  ÀÌ·¸°Ô ÇÏÁö ¸»°í, CHRACTER::CanMove()¿¡
  1440.     //  if (IsStun() || IsDead()) return false;
  1441.     //  ¸¦ Ãß°¡ÇÏ´Â°Ô ¸Â´Ù°í »ý°¢Çϳª,
  1442.     //  ÀÌ¹Ì ´Ù¸¥ ºÎºÐ¿¡¼­ CanMove()´Â IsStun(), IsDead()°ú
  1443.     //  µ¶¸³ÀûÀ¸·Î üũÇϰí Àֱ⠶§¹®¿¡ ¼öÁ¤¿¡ ÀÇÇÑ ¿µÇâÀ»
  1444.     //  ÃÖ¼ÒÈ­Çϱâ À§ÇØ ÀÌ·¸°Ô ¶«»§ Äڵ带 ½á³õ´Â´Ù.
  1445.     if (ch->IsStun() || ch->IsDead())
  1446.         return false;
  1447.     int ComboInterval = dwTime - ch->GetLastComboTime();
  1448.     int HackScalar = 0; // ±âº» ½ºÄ®¶ó ´ÜÀ§ 1
  1449. #if 0
  1450.     sys_log(0, "COMBO: %s arg:%u seq:%u delta:%d checkspeedhack:%d",
  1451.             ch->GetName(), bArg, ch->GetComboSequence(), ComboInterval - ch->GetValidComboInterval(), CheckSpeedHack);
  1452. #endif
  1453.     // bArg 14 ~ 21¹ø ±îÁö ÃÑ 8ÄÞº¸ °¡´É
  1454.     // 1. ù ÄÞº¸(14)´Â ÀÏÁ¤ ½Ã°£ ÀÌÈÄ¿¡ ¹Ýº¹ °¡´É
  1455.     // 2. 15 ~ 21¹øÀº ¹Ýº¹ ºÒ°¡´É
  1456.     // 3. Â÷·Ê´ë·Î Áõ°¡ÇÑ´Ù.
  1457.     if (bArg == 14)
  1458.     {
  1459.         if (CheckSpeedHack && ComboInterval > 0 && ComboInterval < ch->GetValidComboInterval() - COMBO_HACK_ALLOWABLE_MS)
  1460.         {
  1461.             // FIXME ù¹øÂ° ÄÞº¸´Â ÀÌ»óÇÏ°Ô »¡¸® ¿Ã ¼ö°¡ À־ 300À¸·Î ³ª´® -_-;
  1462.  
  1463.             // ´Ù¼öÀÇ ¸ó½ºÅÍ¿¡ ÀÇÇØ ´Ù¿îµÇ´Â »óȲ¿¡¼­ °ø°ÝÀ» Çϸé
  1464.             // ù¹øÂ° ÄÞº¸°¡ ¸Å¿ì ÀûÀº ÀÎÅ͹ú·Î µé¾î¿À´Â »óȲ ¹ß»ý.
  1465.             // ÀÌ·Î ÀÎÇØ ÄÞº¸ÇÙÀ¸·Î ƨ±â´Â °æ¿ì°¡ ÀÖ¾î ´ÙÀ½ ÄÚµå ºñ Ȱ¼ºÈ­.
  1466.             //HackScalar = 1 + (ch->GetValidComboInterval() - ComboInterval) / 300;
  1467.  
  1468.             //sys_log(0, "COMBO_HACK: 2 %s arg:%u interval:%d valid:%u atkspd:%u riding:%s",
  1469.             //      ch->GetName(),
  1470.             //      bArg,
  1471.             //      ComboInterval,
  1472.             //      ch->GetValidComboInterval(),
  1473.             //      ch->GetPoint(POINT_ATT_SPEED),
  1474.             //      ch->IsRiding() ? "yes" : "no");
  1475.         }
  1476.  
  1477.         ch->SetComboSequence(1);
  1478.         ch->SetValidComboInterval((int) (ani_combo_speed(ch, 1) / (ch->GetPoint(POINT_ATT_SPEED) / 100.f)));
  1479.         ch->SetLastComboTime(dwTime);
  1480.     }
  1481.     else if (bArg > 14 && bArg < 22)
  1482.     {
  1483.         int idx = MIN(2, ch->GetComboIndex());
  1484.  
  1485.         if (ch->GetComboSequence() > 5) // ÇöÀç 6ÄÞº¸ ÀÌ»óÀº ¾ø´Ù.
  1486.         {
  1487.             HackScalar = 1;
  1488.             ch->SetValidComboInterval(300);
  1489.             sys_log(0, "COMBO_HACK: 5 %s combo_seq:%d", ch->GetName(), ch->GetComboSequence());
  1490.         }
  1491.         // ÀÚ°´ ½Ö¼ö ÄÞº¸ ¿¹¿Üó¸®
  1492.         else if (bArg == 21 &&
  1493.                  idx == 2 &&
  1494.                  ch->GetComboSequence() == 5 &&
  1495.                  ch->GetJob() == JOB_ASSASSIN &&
  1496.                  ch->GetWear(WEAR_WEAPON) &&
  1497.                  ch->GetWear(WEAR_WEAPON)->GetSubType() == WEAPON_DAGGER)
  1498.             ch->SetValidComboInterval(300);
  1499. #ifdef ENABLE_WOLFMAN_CHARACTER
  1500.         else if (bArg == 21 && idx == 2 && ch->GetComboSequence() == 5 && ch->GetJob() == JOB_WOLFMAN && ch->GetWear(WEAR_WEAPON) && ch->GetWear(WEAR_WEAPON)->GetSubType() == WEAPON_CLAW)
  1501.             ch->SetValidComboInterval(300);
  1502. #endif
  1503.         else if (ComboSequenceBySkillLevel[idx][ch->GetComboSequence()] != bArg)
  1504.         {
  1505.             HackScalar = 1;
  1506.             ch->SetValidComboInterval(300);
  1507.  
  1508.             sys_log(0, "COMBO_HACK: 3 %s arg:%u valid:%u combo_idx:%d combo_seq:%d",
  1509.                     ch->GetName(),
  1510.                     bArg,
  1511.                     ComboSequenceBySkillLevel[idx][ch->GetComboSequence()],
  1512.                     idx,
  1513.                     ch->GetComboSequence());
  1514.         }
  1515.         else
  1516.         {
  1517.             if (CheckSpeedHack && ComboInterval < ch->GetValidComboInterval() - COMBO_HACK_ALLOWABLE_MS)
  1518.             {
  1519.                 HackScalar = 1 + (ch->GetValidComboInterval() - ComboInterval) / 100;
  1520.  
  1521.                 sys_log(0, "COMBO_HACK: 2 %s arg:%u interval:%d valid:%u atkspd:%u riding:%s",
  1522.                         ch->GetName(),
  1523.                         bArg,
  1524.                         ComboInterval,
  1525.                         ch->GetValidComboInterval(),
  1526.                         ch->GetPoint(POINT_ATT_SPEED),
  1527.                         ch->IsRiding() ? "yes" : "no");
  1528.             }
  1529.  
  1530.             // ¸»À» ÅÀÀ» ¶§´Â 15¹ø ~ 16¹øÀ» ¹Ýº¹ÇÑ´Ù
  1531.             //if (ch->IsHorseRiding())
  1532.             if (ch->IsRiding())
  1533.                 ch->SetComboSequence(ch->GetComboSequence() == 1 ? 2 : 1);
  1534.             else
  1535.                 ch->SetComboSequence(ch->GetComboSequence() + 1);
  1536.  
  1537.             ch->SetValidComboInterval((int) (ani_combo_speed(ch, bArg - 13) / (ch->GetPoint(POINT_ATT_SPEED) / 100.f)));
  1538.             ch->SetLastComboTime(dwTime);
  1539.         }
  1540.     }
  1541.     else if (bArg == 13) // ±âº» °ø°Ý (µÐ°©(Polymorph)ÇßÀ» ¶§ ¿Â´Ù)
  1542.     {
  1543.         if (CheckSpeedHack && ComboInterval > 0 && ComboInterval < ch->GetValidComboInterval() - COMBO_HACK_ALLOWABLE_MS)
  1544.         {
  1545.             // ´Ù¼öÀÇ ¸ó½ºÅÍ¿¡ ÀÇÇØ ´Ù¿îµÇ´Â »óȲ¿¡¼­ °ø°ÝÀ» Çϸé
  1546.             // ù¹øÂ° ÄÞº¸°¡ ¸Å¿ì ÀûÀº ÀÎÅ͹ú·Î µé¾î¿À´Â »óȲ ¹ß»ý.
  1547.             // ÀÌ·Î ÀÎÇØ ÄÞº¸ÇÙÀ¸·Î ƨ±â´Â °æ¿ì°¡ ÀÖ¾î ´ÙÀ½ ÄÚµå ºñ Ȱ¼ºÈ­.
  1548.             //HackScalar = 1 + (ch->GetValidComboInterval() - ComboInterval) / 100;
  1549.  
  1550.             //sys_log(0, "COMBO_HACK: 6 %s arg:%u interval:%d valid:%u atkspd:%u",
  1551.             //      ch->GetName(),
  1552.             //      bArg,
  1553.             //      ComboInterval,
  1554.             //      ch->GetValidComboInterval(),
  1555.             //      ch->GetPoint(POINT_ATT_SPEED));
  1556.         }
  1557.  
  1558.         if (ch->GetRaceNum() >= MAIN_RACE_MAX_NUM)
  1559.         {
  1560.             // POLYMORPH_BUG_FIX
  1561.  
  1562.             // DELETEME
  1563.             /*
  1564.             const CMotion * pkMotion = CMotionManager::instance().GetMotion(ch->GetRaceNum(), MAKE_MOTION_KEY(MOTION_MODE_GENERAL, MOTION_NORMAL_ATTACK));
  1565.  
  1566.             if (!pkMotion)
  1567.                 sys_err("cannot find motion by race %u", ch->GetRaceNum());
  1568.             else
  1569.             {
  1570.                 // Á¤»óÀû °è»êÀ̶ó¸é 1000.f¸¦ °öÇØ¾ß ÇÏÁö¸¸ Ŭ¶óÀÌ¾ðÆ®°¡ ¾Ö´Ï¸ÞÀÌ¼Ç ¼ÓµµÀÇ 90%¿¡¼­
  1571.                 // ´ÙÀ½ ¾Ö´Ï¸ÞÀÌ¼Ç ºí·»µùÀ» Çã¿ëÇϹǷΠ900.f¸¦ °öÇÑ´Ù.
  1572.                 int k = (int) (pkMotion->GetDuration() / ((float) ch->GetPoint(POINT_ATT_SPEED) / 100.f) * 900.f);
  1573.                 ch->SetValidComboInterval(k);
  1574.                 ch->SetLastComboTime(dwTime);
  1575.             }
  1576.             */
  1577.             float normalAttackDuration = CMotionManager::instance().GetNormalAttackDuration(ch->GetRaceNum());
  1578.             int k = (int) (normalAttackDuration / ((float) ch->GetPoint(POINT_ATT_SPEED) / 100.f) * 900.f);
  1579.             ch->SetValidComboInterval(k);
  1580.             ch->SetLastComboTime(dwTime);
  1581.             // END_OF_POLYMORPH_BUG_FIX
  1582.         }
  1583.         else
  1584.         {
  1585.             // ¸»ÀÌ ¾ÈµÇ´Â ÄÞº¸°¡ ¿Ô´Ù ÇØÄ¿ÀÏ °¡´É¼º?
  1586.             //if (ch->GetDesc()->DelayedDisconnect(number(2, 9)))
  1587.             //{
  1588.             //  LogManager::instance().HackLog("Hacker", ch);
  1589.             //  sys_log(0, "HACKER: %s arg %u", ch->GetName(), bArg);
  1590.             //}
  1591.  
  1592.             // À§ ÄÚµå·Î ÀÎÇØ, Æú¸®¸ðÇÁ¸¦ Ǫ´Â Áß¿¡ °ø°Ý Çϸé,
  1593.             // °¡²û ÇÙÀ¸·Î ÀνÄÇÏ´Â °æ¿ì°¡ ÀÖ´Ù.
  1594.  
  1595.             // ÀÚ¼¼È÷ ¸»Çô¸é,
  1596.             // ¼­¹ö¿¡¼­ poly 0¸¦ ó¸®ÇßÁö¸¸,
  1597.             // Ŭ¶ó¿¡¼­ ±× ÆÐŶÀ» ¹Þ±â Àü¿¡, ¸÷À» °ø°Ý. <- Áï, ¸÷ÀÎ »óÅ¿¡¼­ °ø°Ý.
  1598.             //
  1599.             // ±×·¯¸é Ŭ¶ó¿¡¼­´Â ¼­¹ö¿¡ ¸÷ »óÅ·Π°ø°ÝÇß´Ù´Â Ä¿¸Çµå¸¦ º¸³»°í (arg == 13)
  1600.             //
  1601.             // ¼­¹ö¿¡¼­´Â race´Â Àΰ£Àε¥ °ø°ÝÇüÅ´ ¸÷ÀÎ ³ðÀÌ´Ù! ¶ó°í ÇÏ¿© ÇÙüũ¸¦ Çß´Ù.
  1602.  
  1603.             // »ç½Ç °ø°Ý ÆÐÅÏ¿¡ ´ëÇÑ °ÍÀº Ŭ¶óÀÌ¾ðÆ®¿¡¼­ ÆÇ´ÜÇØ¼­ º¸³¾ °ÍÀÌ ¾Æ´Ï¶ó,
  1604.             // ¼­¹ö¿¡¼­ ÆÇ´ÜÇØ¾ß ÇÒ °ÍÀε¥... ¿Ö ÀÌ·¸°Ô ÇØ³ùÀ»±î...
  1605.             // by rtsummit
  1606.         }
  1607.     }
  1608.     else
  1609.     {
  1610.         // ¸»ÀÌ ¾ÈµÇ´Â ÄÞº¸°¡ ¿Ô´Ù ÇØÄ¿ÀÏ °¡´É¼º?
  1611.         if (ch->GetDesc()->DelayedDisconnect(number(2, 9)))
  1612.         {
  1613.             LogManager::instance().HackLog("Hacker", ch);
  1614.             sys_log(0, "HACKER: %s arg %u", ch->GetName(), bArg);
  1615.         }
  1616.  
  1617.         HackScalar = 10;
  1618.         ch->SetValidComboInterval(300);
  1619.     }
  1620.  
  1621.     if (HackScalar)
  1622.     {
  1623.         // ¸»¿¡ Ÿ°Å³ª ³»·ÈÀ» ¶§ 1.5Ãʰ£ °ø°ÝÀº ÇÙÀ¸·Î °£ÁÖÇÏÁö ¾ÊµÇ °ø°Ý·ÂÀº ¾ø°Ô Çϴ ó¸®
  1624.         if (get_dword_time() - ch->GetLastMountTime() > 1500)
  1625.             ch->IncreaseComboHackCount(1 + HackScalar);
  1626.  
  1627.         ch->SkipComboAttackByTime(ch->GetValidComboInterval());
  1628.     }
  1629.  
  1630.     return HackScalar;
  1631.  
  1632.  
  1633. }
  1634.  
  1635. void CInputMain::Move(LPCHARACTER ch, const char * data)
  1636. {
  1637.     if (!ch->CanMove())
  1638.         return;
  1639.  
  1640.     struct command_move * pinfo = (struct command_move *) data;
  1641.  
  1642.     if (pinfo->bFunc >= FUNC_MAX_NUM && !(pinfo->bFunc & 0x80))
  1643.     {
  1644.         sys_err("invalid move type: %s", ch->GetName());
  1645.         return;
  1646.     }
  1647.  
  1648.     //enum EMoveFuncType
  1649.     //{
  1650.     //  FUNC_WAIT,
  1651.     //  FUNC_MOVE,
  1652.     //  FUNC_ATTACK,
  1653.     //  FUNC_COMBO,
  1654.     //  FUNC_MOB_SKILL,
  1655.     //  _FUNC_SKILL,
  1656.     //  FUNC_MAX_NUM,
  1657.     //  FUNC_SKILL = 0x80,
  1658.     //};
  1659.  
  1660.     // ÅÚ·¹Æ÷Æ® Ç٠üũ
  1661.  
  1662. //  if (!test_server)
  1663.     {
  1664.         const float fDist = DISTANCE_SQRT((ch->GetX() - pinfo->lX) / 100, (ch->GetY() - pinfo->lY) / 100);
  1665.         // @fixme106 (changed 40 to 60)
  1666.         if (((false == ch->IsRiding() && fDist > 25) || fDist > 60) && OXEVENT_MAP_INDEX != ch->GetMapIndex())
  1667.         {
  1668. #ifdef ENABLE_HACK_TELEPORT_LOG // @warme006
  1669.             {
  1670.                 const PIXEL_POSITION & warpPos = ch->GetWarpPosition();
  1671.  
  1672.                 if (warpPos.x == 0 && warpPos.y == 0)
  1673.                     LogManager::instance().HackLog("Teleport", ch); // ºÎÁ¤È®ÇÒ ¼ö ÀÖÀ½
  1674.             }
  1675. #endif
  1676.             sys_log(0, "MOVE: %s trying to move too far (dist: %.1fm) Riding(%d)", ch->GetName(), fDist, ch->IsRiding());
  1677.  
  1678.             ch->Show(ch->GetMapIndex(), ch->GetX(), ch->GetY(), ch->GetZ());
  1679.             ch->Stop();
  1680.             return;
  1681.         }
  1682. #ifdef ENABLE_CHECK_GHOSTMODE
  1683.         if (ch->IsPC() && ch->IsDead())
  1684.         {
  1685.             sys_log(0, "MOVE: %s trying to move as dead", ch->GetName());
  1686.  
  1687.             ch->Show(ch->GetMapIndex(), ch->GetX(), ch->GetY(), ch->GetZ());
  1688.             ch->Stop();
  1689.             return;
  1690.         }
  1691. #endif
  1692.         //
  1693.         // ½ºÇǵåÇÙ(SPEEDHACK) Check
  1694.         //
  1695.         DWORD dwCurTime = get_dword_time();
  1696.         // ½Ã°£À» SyncÇϰí 7ÃÊ ÈÄ ºÎÅÍ °Ë»çÇÑ´Ù. (20090702 ÀÌÀü¿£ 5ÃÊ¿´À½)
  1697.         bool CheckSpeedHack = (false == ch->GetDesc()->IsHandshaking() && dwCurTime - ch->GetDesc()->GetClientTime() > 7000);
  1698.  
  1699.         if (CheckSpeedHack)
  1700.         {
  1701.             int iDelta = (int) (pinfo->dwTime - ch->GetDesc()->GetClientTime());
  1702.             int iServerDelta = (int) (dwCurTime - ch->GetDesc()->GetClientTime());
  1703.  
  1704.             iDelta = (int) (dwCurTime - pinfo->dwTime);
  1705.  
  1706.             // ½Ã°£ÀÌ ´Ê°Ô°£´Ù. ÀÏ´Ü ·Î±×¸¸ ÇØµÐ´Ù. ÁøÂ¥ ÀÌ·± »ç¶÷µéÀÌ ¸¹ÀºÁö Ã¼Å©ÇØ¾ßÇÔ. TODO
  1707.             if (iDelta >= 30000)
  1708.             {
  1709.                 sys_log(0, "SPEEDHACK: slow timer name %s delta %d", ch->GetName(), iDelta);
  1710.                 ch->GetDesc()->DelayedDisconnect(3);
  1711.             }
  1712.             // 1ÃÊ¿¡ 20msec »¡¸® °¡´Â°Å ±îÁö´Â ÀÌÇØÇÑ´Ù.
  1713.             else if (iDelta < -(iServerDelta / 50))
  1714.             {
  1715.                 sys_log(0, "SPEEDHACK: DETECTED! %s (delta %d %d)", ch->GetName(), iDelta, iServerDelta);
  1716.                 ch->GetDesc()->DelayedDisconnect(3);
  1717.             }
  1718.         }
  1719.  
  1720.         //
  1721.         // ÄÞº¸ÇÙ ¹× ½ºÇǵåÇ٠üũ
  1722.         //
  1723.         if (pinfo->bFunc == FUNC_COMBO && g_bCheckMultiHack)
  1724.         {
  1725.             CheckComboHack(ch, pinfo->bArg, pinfo->dwTime, CheckSpeedHack); // ÄÞº¸ üũ
  1726.         }
  1727.     }
  1728.  
  1729.     if (pinfo->bFunc == FUNC_MOVE)
  1730.     {
  1731.         if (ch->GetLimitPoint(POINT_MOV_SPEED) == 0)
  1732.             return;
  1733.  
  1734.         ch->SetRotation(pinfo->bRot * 5);   // Áߺ¹ ÄÚµå
  1735.         ch->ResetStopTime();                // ""
  1736.  
  1737.         ch->Goto(pinfo->lX, pinfo->lY);
  1738.     }
  1739.     else
  1740.     {
  1741.         if (pinfo->bFunc == FUNC_ATTACK || pinfo->bFunc == FUNC_COMBO)
  1742.             ch->OnMove(true);
  1743.         else if (pinfo->bFunc & FUNC_SKILL)
  1744.         {
  1745.             const int MASK_SKILL_MOTION = 0x7F;
  1746.             unsigned int motion = pinfo->bFunc & MASK_SKILL_MOTION;
  1747.  
  1748.             if (!ch->IsUsableSkillMotion(motion))
  1749.             {
  1750.                 const char* name = ch->GetName();
  1751.                 unsigned int job = ch->GetJob();
  1752.                 unsigned int group = ch->GetSkillGroup();
  1753.  
  1754.                 char szBuf[256];
  1755.                 snprintf(szBuf, sizeof(szBuf), "SKILL_HACK: name=%s, job=%d, group=%d, motion=%d", name, job, group, motion);
  1756.                 LogManager::instance().HackLog(szBuf, ch->GetDesc()->GetAccountTable().login, ch->GetName(), ch->GetDesc()->GetHostName());
  1757.                 sys_log(0, "%s", szBuf);
  1758.  
  1759.                 if (test_server)
  1760.                 {
  1761.                     ch->GetDesc()->DelayedDisconnect(number(2, 8));
  1762.                     ch->ChatPacket(CHAT_TYPE_INFO, szBuf);
  1763.                 }
  1764.                 else
  1765.                 {
  1766.                     ch->GetDesc()->DelayedDisconnect(number(150, 500));
  1767.                 }
  1768.             }
  1769.  
  1770.             ch->OnMove();
  1771.         }
  1772.  
  1773.         ch->SetRotation(pinfo->bRot * 5);   // Áߺ¹ ÄÚµå
  1774.         ch->ResetStopTime();                // ""
  1775.  
  1776.         ch->Move(pinfo->lX, pinfo->lY);
  1777.         ch->Stop();
  1778.         ch->StopStaminaConsume();
  1779.     }
  1780.  
  1781.     TPacketGCMove pack;
  1782.  
  1783.     pack.bHeader      = HEADER_GC_MOVE;
  1784.     pack.bFunc        = pinfo->bFunc;
  1785.     pack.bArg         = pinfo->bArg;
  1786.     pack.bRot         = pinfo->bRot;
  1787.     pack.dwVID        = ch->GetVID();
  1788.     pack.lX           = pinfo->lX;
  1789.     pack.lY           = pinfo->lY;
  1790.     pack.dwTime       = pinfo->dwTime;
  1791.     pack.dwDuration   = (pinfo->bFunc == FUNC_MOVE) ? ch->GetCurrentMoveDuration() : 0;
  1792.  
  1793.     ch->PacketAround(&pack, sizeof(TPacketGCMove), ch);
  1794. /*
  1795.     if (pinfo->dwTime == 10653691) // µð¹ö°Å ¹ß°ß
  1796.     {
  1797.         if (ch->GetDesc()->DelayedDisconnect(number(15, 30)))
  1798.             LogManager::instance().HackLog("Debugger", ch);
  1799.  
  1800.     }
  1801.     else if (pinfo->dwTime == 10653971) // Softice ¹ß°ß
  1802.     {
  1803.         if (ch->GetDesc()->DelayedDisconnect(number(15, 30)))
  1804.             LogManager::instance().HackLog("Softice", ch);
  1805.     }
  1806. */
  1807.     /*
  1808.     sys_log(0,
  1809.             "MOVE: %s Func:%u Arg:%u Pos:%dx%d Time:%u Dist:%.1f",
  1810.             ch->GetName(),
  1811.             pinfo->bFunc,
  1812.             pinfo->bArg,
  1813.             pinfo->lX / 100,
  1814.             pinfo->lY / 100,
  1815.             pinfo->dwTime,
  1816.             fDist);
  1817.     */
  1818. }
  1819.  
  1820. void CInputMain::Attack(LPCHARACTER ch, const BYTE header, const char* data)
  1821. {
  1822.     if (NULL == ch)
  1823.         return;
  1824.  
  1825.     struct type_identifier
  1826.     {
  1827.         BYTE header;
  1828.         BYTE type;
  1829.     };
  1830.  
  1831.     const struct type_identifier* const type = reinterpret_cast<const struct type_identifier*>(data);
  1832.  
  1833.     if (type->type > 0)
  1834.     {
  1835.         if (false == ch->CanUseSkill(type->type))
  1836.         {
  1837.             return;
  1838.         }
  1839.  
  1840.         switch (type->type)
  1841.         {
  1842.             case SKILL_GEOMPUNG:
  1843.             case SKILL_SANGONG:
  1844.             case SKILL_YEONSA:
  1845.             case SKILL_KWANKYEOK:
  1846.             case SKILL_HWAJO:
  1847.             case SKILL_GIGUNG:
  1848.             case SKILL_PABEOB:
  1849.             case SKILL_MARYUNG:
  1850.             case SKILL_TUSOK:
  1851.             case SKILL_MAHWAN:
  1852.             case SKILL_BIPABU:
  1853.             case SKILL_NOEJEON:
  1854.             case SKILL_CHAIN:
  1855.             case SKILL_HORSE_WILDATTACK_RANGE:
  1856.                 if (HEADER_CG_SHOOT != type->header)
  1857.                 {
  1858.                     if (test_server)
  1859.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Attack :name[%s] Vnum[%d] can't use skill by attack(warning)"), type->type);
  1860.                     return;
  1861.                 }
  1862.                 break;
  1863.         }
  1864.     }
  1865.  
  1866.     switch (header)
  1867.     {
  1868.         case HEADER_CG_ATTACK:
  1869.             {
  1870.                 if (NULL == ch->GetDesc())
  1871.                     return;
  1872.  
  1873.                 const TPacketCGAttack* const packMelee = reinterpret_cast<const TPacketCGAttack*>(data);
  1874.  
  1875.                 ch->GetDesc()->AssembleCRCMagicCube(packMelee->bCRCMagicCubeProcPiece, packMelee->bCRCMagicCubeFilePiece);
  1876.  
  1877.                 LPCHARACTER victim = CHARACTER_MANAGER::instance().Find(packMelee->dwVID);
  1878.  
  1879.                 if (NULL == victim || ch == victim)
  1880.                     return;
  1881.  
  1882.                 switch (victim->GetCharType())
  1883.                 {
  1884.                     case CHAR_TYPE_NPC:
  1885.                     case CHAR_TYPE_WARP:
  1886.                     case CHAR_TYPE_GOTO:
  1887.                         return;
  1888.                 }
  1889.  
  1890.                 if (packMelee->bType > 0)
  1891.                 {
  1892.                     if (false == ch->CheckSkillHitCount(packMelee->bType, victim->GetVID()))
  1893.                     {
  1894.                         return;
  1895.                     }
  1896.                 }
  1897.  
  1898.                 ch->Attack(victim, packMelee->bType);
  1899.             }
  1900.             break;
  1901.  
  1902.         case HEADER_CG_SHOOT:
  1903.             {
  1904.                 const TPacketCGShoot* const packShoot = reinterpret_cast<const TPacketCGShoot*>(data);
  1905.  
  1906.                 ch->Shoot(packShoot->bType);
  1907.             }
  1908.             break;
  1909.     }
  1910. }
  1911.  
  1912. int CInputMain::SyncPosition(LPCHARACTER ch, const char * c_pcData, size_t uiBytes)
  1913. {
  1914.     const TPacketCGSyncPosition* pinfo = reinterpret_cast<const TPacketCGSyncPosition*>( c_pcData );
  1915.  
  1916.     if (uiBytes < pinfo->wSize)
  1917.         return -1;
  1918.  
  1919.     int iExtraLen = pinfo->wSize - sizeof(TPacketCGSyncPosition);
  1920.  
  1921.     if (iExtraLen < 0)
  1922.     {
  1923.         sys_err("invalid packet length (len %d size %u buffer %u)", iExtraLen, pinfo->wSize, uiBytes);
  1924.         ch->GetDesc()->SetPhase(PHASE_CLOSE);
  1925.         return -1;
  1926.     }
  1927.  
  1928.     if (0 != (iExtraLen % sizeof(TPacketCGSyncPositionElement)))
  1929.     {
  1930.         sys_err("invalid packet length %d (name: %s)", pinfo->wSize, ch->GetName());
  1931.         return iExtraLen;
  1932.     }
  1933.  
  1934.     int iCount = iExtraLen / sizeof(TPacketCGSyncPositionElement);
  1935.  
  1936.     if (iCount <= 0)
  1937.         return iExtraLen;
  1938.  
  1939.     static const int nCountLimit = 16;
  1940.  
  1941.     if( iCount > nCountLimit )
  1942.     {
  1943.         //LogManager::instance().HackLog( "SYNC_POSITION_HACK", ch );
  1944.         sys_err( "Too many SyncPosition Count(%d) from Name(%s)", iCount, ch->GetName() );
  1945.         //ch->GetDesc()->SetPhase(PHASE_CLOSE);
  1946.         //return -1;
  1947.         iCount = nCountLimit;
  1948.     }
  1949.  
  1950.     TEMP_BUFFER tbuf;
  1951.     LPBUFFER lpBuf = tbuf.getptr();
  1952.  
  1953.     TPacketGCSyncPosition * pHeader = (TPacketGCSyncPosition *) buffer_write_peek(lpBuf);
  1954.     buffer_write_proceed(lpBuf, sizeof(TPacketGCSyncPosition));
  1955.  
  1956.     const TPacketCGSyncPositionElement* e =
  1957.         reinterpret_cast<const TPacketCGSyncPositionElement*>(c_pcData + sizeof(TPacketCGSyncPosition));
  1958.  
  1959.     timeval tvCurTime;
  1960.     gettimeofday(&tvCurTime, NULL);
  1961.  
  1962.     for (int i = 0; i < iCount; ++i, ++e)
  1963.     {
  1964.         LPCHARACTER victim = CHARACTER_MANAGER::instance().Find(e->dwVID);
  1965.  
  1966.         if (!victim)
  1967.             continue;
  1968.  
  1969.         switch (victim->GetCharType())
  1970.         {
  1971.             case CHAR_TYPE_NPC:
  1972.             case CHAR_TYPE_WARP:
  1973.             case CHAR_TYPE_GOTO:
  1974.                 continue;
  1975.         }
  1976.  
  1977.         // ¼ÒÀ¯±Ç °Ë»ç
  1978.         if (!victim->SetSyncOwner(ch))
  1979.             continue;
  1980.  
  1981.         const float fDistWithSyncOwner = DISTANCE_SQRT( (victim->GetX() - ch->GetX()) / 100, (victim->GetY() - ch->GetY()) / 100 );
  1982.         static const float fLimitDistWithSyncOwner = 2500.f + 1000.f;
  1983.         // victim°úÀÇ °Å¸®°¡ 2500 + a ÀÌ»óÀ̸é ÇÙÀ¸·Î °£ÁÖ.
  1984.         //  °Å¸® ÂüÁ¶ : Ŭ¶óÀ̾ðÆ®ÀÇ __GetSkillTargetRange, __GetBowRange ÇÔ¼ö
  1985.         //  2500 : ½ºÅ³ proto¿¡¼­ °¡Àå »ç°Å¸®°¡ ±ä ½ºÅ³ÀÇ »ç°Å¸®, ¶Ç´Â ȰÀÇ »ç°Å¸®
  1986.         //  a = POINT_BOW_DISTANCE °ª... Àε¥ ½ÇÁ¦·Î »ç¿ëÇÏ´Â °ªÀÎÁö´Â Àß ¸ð¸£°ÚÀ½. ¾ÆÀÌÅÛÀ̳ª Æ÷¼Ç, ½ºÅ³, Äù½ºÆ®¿¡´Â ¾ø´Âµ¥...
  1987.         //      ±×·¡µµ Ȥ½Ã³ª ÇÏ´Â ¸¶À½¿¡ ¹öÆÛ·Î »ç¿ëÇÒ °âÇØ¼­ 1000.f ·Î µÒ...
  1988.         if (fDistWithSyncOwner > fLimitDistWithSyncOwner)
  1989.         {
  1990.             // g_iSyncHackLimitCount¹ø ±îÁö´Â ºÁÁÜ.
  1991.             if (ch->GetSyncHackCount() < g_iSyncHackLimitCount)
  1992.             {
  1993.                 ch->SetSyncHackCount(ch->GetSyncHackCount() + 1);
  1994.                 continue;
  1995.             }
  1996.             else
  1997.             {
  1998.                 LogManager::instance().HackLog( "SYNC_POSITION_HACK", ch );
  1999.  
  2000.                 sys_err( "Too far SyncPosition DistanceWithSyncOwner(%f)(%s) from Name(%s) CH(%d,%d) VICTIM(%d,%d) SYNC(%d,%d)",
  2001.                     fDistWithSyncOwner, victim->GetName(), ch->GetName(), ch->GetX(), ch->GetY(), victim->GetX(), victim->GetY(),
  2002.                     e->lX, e->lY );
  2003.  
  2004.                 ch->GetDesc()->SetPhase(PHASE_CLOSE);
  2005.  
  2006.                 return -1;
  2007.             }
  2008.         }
  2009.  
  2010.         const float fDist = DISTANCE_SQRT( (victim->GetX() - e->lX) / 100, (victim->GetY() - e->lY) / 100 );
  2011.         static const long g_lValidSyncInterval = 100 * 1000; // 100ms
  2012.         const timeval &tvLastSyncTime = victim->GetLastSyncTime();
  2013.         timeval *tvDiff = timediff(&tvCurTime, &tvLastSyncTime);
  2014.  
  2015.         // SyncPositionÀ» ¾Ç¿ëÇÏ¿© ŸÀ¯Àú¸¦ ÀÌ»óÇÑ °÷À¸·Î º¸³»´Â ÇÙ ¹æ¾îÇϱâ À§ÇÏ¿©,
  2016.         // °°Àº À¯Àú¸¦ g_lValidSyncInterval ms À̳»¿¡ ´Ù½Ã SyncPositionÇÏ·Á°í Çϸé ÇÙÀ¸·Î °£ÁÖ.
  2017.         if (tvDiff->tv_sec == 0 && tvDiff->tv_usec < g_lValidSyncInterval)
  2018.         {
  2019.             // g_iSyncHackLimitCount¹ø ±îÁö´Â ºÁÁÜ.
  2020.             if (ch->GetSyncHackCount() < g_iSyncHackLimitCount)
  2021.             {
  2022.                 ch->SetSyncHackCount(ch->GetSyncHackCount() + 1);
  2023.                 continue;
  2024.             }
  2025.             else
  2026.             {
  2027.                 LogManager::instance().HackLog( "SYNC_POSITION_HACK", ch );
  2028.  
  2029.                 sys_err( "Too often SyncPosition Interval(%ldms)(%s) from Name(%s) VICTIM(%d,%d) SYNC(%d,%d)",
  2030.                     tvDiff->tv_sec * 1000 + tvDiff->tv_usec / 1000, victim->GetName(), ch->GetName(), victim->GetX(), victim->GetY(),
  2031.                     e->lX, e->lY );
  2032.  
  2033.                 ch->GetDesc()->SetPhase(PHASE_CLOSE);
  2034.  
  2035.                 return -1;
  2036.             }
  2037.         }
  2038.         else if( fDist > 25.0f )
  2039.         {
  2040.             LogManager::instance().HackLog( "SYNC_POSITION_HACK", ch );
  2041.  
  2042.             sys_err( "Too far SyncPosition Distance(%f)(%s) from Name(%s) CH(%d,%d) VICTIM(%d,%d) SYNC(%d,%d)",
  2043.                     fDist, victim->GetName(), ch->GetName(), ch->GetX(), ch->GetY(), victim->GetX(), victim->GetY(),
  2044.                   e->lX, e->lY );
  2045.  
  2046.             ch->GetDesc()->SetPhase(PHASE_CLOSE);
  2047.  
  2048.             return -1;
  2049.         }
  2050.         else
  2051.         {
  2052.             victim->SetLastSyncTime(tvCurTime);
  2053.             victim->Sync(e->lX, e->lY);
  2054.             buffer_write(lpBuf, e, sizeof(TPacketCGSyncPositionElement));
  2055.         }
  2056.     }
  2057.  
  2058.     if (buffer_size(lpBuf) != sizeof(TPacketGCSyncPosition))
  2059.     {
  2060.         pHeader->bHeader = HEADER_GC_SYNC_POSITION;
  2061.         pHeader->wSize = buffer_size(lpBuf);
  2062.  
  2063.         ch->PacketAround(buffer_read_peek(lpBuf), buffer_size(lpBuf), ch);
  2064.     }
  2065.  
  2066.     return iExtraLen;
  2067. }
  2068.  
  2069. void CInputMain::FlyTarget(LPCHARACTER ch, const char * pcData, BYTE bHeader)
  2070. {
  2071.     TPacketCGFlyTargeting * p = (TPacketCGFlyTargeting *) pcData;
  2072.     ch->FlyTarget(p->dwTargetVID, p->x, p->y, bHeader);
  2073. }
  2074.  
  2075. void CInputMain::UseSkill(LPCHARACTER ch, const char * pcData)
  2076. {
  2077.     TPacketCGUseSkill * p = (TPacketCGUseSkill *) pcData;
  2078.     ch->UseSkill(p->dwVnum, CHARACTER_MANAGER::instance().Find(p->dwVID));
  2079. }
  2080.  
  2081. void CInputMain::ScriptButton(LPCHARACTER ch, const void* c_pData)
  2082. {
  2083.     TPacketCGScriptButton * p = (TPacketCGScriptButton *) c_pData;
  2084.     sys_log(0, "QUEST ScriptButton pid %d idx %u", ch->GetPlayerID(), p->idx);
  2085.  
  2086.     quest::PC* pc = quest::CQuestManager::instance().GetPCForce(ch->GetPlayerID());
  2087.     if (pc && pc->IsConfirmWait())
  2088.     {
  2089.         quest::CQuestManager::instance().Confirm(ch->GetPlayerID(), quest::CONFIRM_TIMEOUT);
  2090.     }
  2091.     else if (p->idx & 0x80000000)
  2092.     {
  2093.         //Äù½ºÆ® â¿¡¼­ Ŭ¸¯½Ã(__SelectQuest) ¿©±â·Î
  2094.         quest::CQuestManager::Instance().QuestInfo(ch->GetPlayerID(), p->idx & 0x7fffffff);
  2095.     }
  2096.     else
  2097.     {
  2098.         quest::CQuestManager::Instance().QuestButton(ch->GetPlayerID(), p->idx);
  2099.     }
  2100. }
  2101.  
  2102. void CInputMain::ScriptAnswer(LPCHARACTER ch, const void* c_pData)
  2103. {
  2104.     TPacketCGScriptAnswer * p = (TPacketCGScriptAnswer *) c_pData;
  2105.     sys_log(0, "QUEST ScriptAnswer pid %d answer %d", ch->GetPlayerID(), p->answer);
  2106.  
  2107.     if (p->answer > 250) // ´ÙÀ½ ¹öư¿¡ ´ëÇÑ ÀÀ´äÀ¸·Î ¿Â ÆÐŶÀÎ °æ¿ì
  2108.     {
  2109.         quest::CQuestManager::Instance().Resume(ch->GetPlayerID());
  2110.     }
  2111.     else // ¼±Åà ¹öưÀ» °ñ¶ó¼­ ¿Â ÆÐŶÀÎ °æ¿ì
  2112.     {
  2113.         quest::CQuestManager::Instance().Select(ch->GetPlayerID(),  p->answer);
  2114.     }
  2115. }
  2116.  
  2117.  
  2118. // SCRIPT_SELECT_ITEM
  2119. void CInputMain::ScriptSelectItem(LPCHARACTER ch, const void* c_pData)
  2120. {
  2121.     TPacketCGScriptSelectItem* p = (TPacketCGScriptSelectItem*) c_pData;
  2122.     sys_log(0, "QUEST ScriptSelectItem pid %d answer %d", ch->GetPlayerID(), p->selection);
  2123.     quest::CQuestManager::Instance().SelectItem(ch->GetPlayerID(), p->selection);
  2124. }
  2125. // END_OF_SCRIPT_SELECT_ITEM
  2126.  
  2127. void CInputMain::QuestInputString(LPCHARACTER ch, const void* c_pData)
  2128. {
  2129.     TPacketCGQuestInputString * p = (TPacketCGQuestInputString*) c_pData;
  2130.  
  2131.     char msg[65];
  2132.     strlcpy(msg, p->msg, sizeof(msg));
  2133.     sys_log(0, "QUEST InputString pid %u msg %s", ch->GetPlayerID(), msg);
  2134.  
  2135.     quest::CQuestManager::Instance().Input(ch->GetPlayerID(), msg);
  2136. }
  2137.  
  2138. void CInputMain::QuestConfirm(LPCHARACTER ch, const void* c_pData)
  2139. {
  2140.     TPacketCGQuestConfirm* p = (TPacketCGQuestConfirm*) c_pData;
  2141.     LPCHARACTER ch_wait = CHARACTER_MANAGER::instance().FindByPID(p->requestPID);
  2142.     if (p->answer)
  2143.         p->answer = quest::CONFIRM_YES;
  2144.     sys_log(0, "QuestConfirm from %s pid %u name %s answer %d", ch->GetName(), p->requestPID, (ch_wait)?ch_wait->GetName():"", p->answer);
  2145.     if (ch_wait)
  2146.     {
  2147.         quest::CQuestManager::Instance().Confirm(ch_wait->GetPlayerID(), (quest::EQuestConfirmType) p->answer, ch->GetPlayerID());
  2148.     }
  2149. }
  2150.  
  2151. void CInputMain::Target(LPCHARACTER ch, const char * pcData)
  2152. {
  2153.     TPacketCGTarget * p = (TPacketCGTarget *) pcData;
  2154.  
  2155.     building::LPOBJECT pkObj = building::CManager::instance().FindObjectByVID(p->dwVID);
  2156.  
  2157.     if (pkObj)
  2158.     {
  2159.         TPacketGCTarget pckTarget;
  2160.         pckTarget.header = HEADER_GC_TARGET;
  2161.         pckTarget.dwVID = p->dwVID;
  2162.         ch->GetDesc()->Packet(&pckTarget, sizeof(TPacketGCTarget));
  2163.     }
  2164.     else
  2165.         ch->SetTarget(CHARACTER_MANAGER::instance().Find(p->dwVID));
  2166. }
  2167.  
  2168. void CInputMain::Warp(LPCHARACTER ch, const char * pcData)
  2169. {
  2170.     ch->WarpEnd();
  2171. }
  2172.  
  2173. void CInputMain::SafeboxCheckin(LPCHARACTER ch, const char * c_pData)
  2174. {
  2175.     if (quest::CQuestManager::instance().GetPCForce(ch->GetPlayerID())->IsRunning() == true)
  2176.         return;
  2177.  
  2178.     TPacketCGSafeboxCheckin * p = (TPacketCGSafeboxCheckin *) c_pData;
  2179.  
  2180.     if (!ch->CanHandleItem())
  2181.         return;
  2182.  
  2183.     CSafebox * pkSafebox = ch->GetSafebox();
  2184.     LPITEM pkItem = ch->GetItem(p->ItemPos);
  2185.  
  2186.     if (!pkSafebox || !pkItem)
  2187.         return;
  2188.  
  2189.     if (pkItem->GetCell() >= INVENTORY_MAX_NUM && IS_SET(pkItem->GetFlag(), ITEM_FLAG_IRREMOVABLE))
  2190.     {
  2191.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> â°í·Î ¿Å±æ ¼ö ¾ø´Â ¾ÆÀÌÅÛ ÀÔ´Ï´Ù."));
  2192.         return;
  2193.     }
  2194.  
  2195.     if (!pkSafebox->IsEmpty(p->bSafePos, pkItem->GetSize()))
  2196.     {
  2197.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> ¿Å±æ ¼ö ¾ø´Â À§Ä¡ÀÔ´Ï´Ù."));
  2198.         return;
  2199.     }
  2200.  
  2201.     if (pkItem->GetVnum() == UNIQUE_ITEM_SAFEBOX_EXPAND)
  2202.     {
  2203.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> ÀÌ ¾ÆÀÌÅÛÀº ³ÖÀ» ¼ö ¾ø½À´Ï´Ù."));
  2204.         return;
  2205.     }
  2206.  
  2207.     if( IS_SET(pkItem->GetAntiFlag(), ITEM_ANTIFLAG_SAFEBOX) )
  2208.     {
  2209.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> ÀÌ ¾ÆÀÌÅÛÀº ³ÖÀ» ¼ö ¾ø½À´Ï´Ù."));
  2210.         return;
  2211.     }
  2212.  
  2213.     if (true == pkItem->isLocked())
  2214.     {
  2215.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> ÀÌ ¾ÆÀÌÅÛÀº ³ÖÀ» ¼ö ¾ø½À´Ï´Ù."));
  2216.         return;
  2217.     }
  2218.  
  2219.     pkItem->RemoveFromCharacter();
  2220.     if (!pkItem->IsDragonSoul())
  2221.         ch->SyncQuickslot(QUICKSLOT_TYPE_ITEM, p->ItemPos.cell, 255);
  2222.     pkSafebox->Add(p->bSafePos, pkItem);
  2223.  
  2224.     char szHint[128];
  2225.     snprintf(szHint, sizeof(szHint), "%s %u", pkItem->GetName(), pkItem->GetCount());
  2226.     LogManager::instance().ItemLog(ch, pkItem, "SAFEBOX PUT", szHint);
  2227. }
  2228.  
  2229. void CInputMain::SafeboxCheckout(LPCHARACTER ch, const char * c_pData, bool bMall)
  2230. {
  2231.     TPacketCGSafeboxCheckout * p = (TPacketCGSafeboxCheckout *) c_pData;
  2232.  
  2233.     if (!ch->CanHandleItem())
  2234.         return;
  2235.  
  2236.     CSafebox * pkSafebox;
  2237.  
  2238.     if (bMall)
  2239.         pkSafebox = ch->GetMall();
  2240.     else
  2241.         pkSafebox = ch->GetSafebox();
  2242.  
  2243.     if (!pkSafebox)
  2244.         return;
  2245.  
  2246.     LPITEM pkItem = pkSafebox->Get(p->bSafePos);
  2247.  
  2248.     if (!pkItem)
  2249.         return;
  2250.  
  2251.     if (!ch->IsEmptyItemGrid(p->ItemPos, pkItem->GetSize()))
  2252.         return;
  2253.  
  2254.     // ¾ÆÀÌÅÛ ¸ô¿¡¼­ Àκ¥À¸·Î ¿Å±â´Â ºÎºÐ¿¡¼­ ¿ëÈ¥¼® Ư¼ö ó¸®
  2255.     // (¸ô¿¡¼­ ¸¸µå´Â ¾ÆÀÌÅÛÀº item_proto¿¡ Á¤Àǵȴë·Î ¼Ó¼ºÀÌ ºÙ±â ¶§¹®¿¡,
  2256.     //  ¿ëÈ¥¼®ÀÇ °æ¿ì, ÀÌ Ã³¸®¸¦ ÇÏÁö ¾ÊÀ¸¸é ¼Ó¼ºÀÌ Çϳªµµ ºÙÁö ¾Ê°Ô µÈ´Ù.)
  2257.     if (pkItem->IsDragonSoul())
  2258.     {
  2259.         if (bMall)
  2260.         {
  2261.             DSManager::instance().DragonSoulItemInitialize(pkItem);
  2262.         }
  2263.  
  2264.         if (DRAGON_SOUL_INVENTORY != p->ItemPos.window_type)
  2265.         {
  2266.             ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> ¿Å±æ ¼ö ¾ø´Â À§Ä¡ÀÔ´Ï´Ù."));
  2267.             return;
  2268.         }
  2269.  
  2270.         TItemPos DestPos = p->ItemPos;
  2271.         if (!DSManager::instance().IsValidCellForThisItem(pkItem, DestPos))
  2272.         {
  2273.             int iCell = ch->GetEmptyDragonSoulInventory(pkItem);
  2274.             if (iCell < 0)
  2275.             {
  2276.                 ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> ¿Å±æ ¼ö ¾ø´Â À§Ä¡ÀÔ´Ï´Ù."));
  2277.                 return ;
  2278.             }
  2279.             DestPos = TItemPos (DRAGON_SOUL_INVENTORY, iCell);
  2280.         }
  2281.  
  2282.         pkSafebox->Remove(p->bSafePos);
  2283.         pkItem->AddToCharacter(ch, DestPos);
  2284.         ITEM_MANAGER::instance().FlushDelayedSave(pkItem);
  2285.     }
  2286.     else
  2287.     {
  2288.         if (DRAGON_SOUL_INVENTORY == p->ItemPos.window_type)
  2289.         {
  2290.             ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<â°í> ¿Å±æ ¼ö ¾ø´Â À§Ä¡ÀÔ´Ï´Ù."));
  2291.             return;
  2292.         }
  2293.         // @fixme119
  2294.         if (p->ItemPos.IsBeltInventoryPosition() && false == CBeltInventoryHelper::CanMoveIntoBeltInventory(pkItem))
  2295.         {
  2296.             ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ÀÌ ¾ÆÀÌÅÛÀº º§Æ® Àκ¥Å丮·Î ¿Å±æ ¼ö ¾ø½À´Ï´Ù."));
  2297.             return;
  2298.         }
  2299.  
  2300.         pkSafebox->Remove(p->bSafePos);
  2301.         pkItem->AddToCharacter(ch, p->ItemPos);
  2302.         ITEM_MANAGER::instance().FlushDelayedSave(pkItem);
  2303.     }
  2304.  
  2305.     DWORD dwID = pkItem->GetID();
  2306.     db_clientdesc->DBPacketHeader(HEADER_GD_ITEM_FLUSH, 0, sizeof(DWORD));
  2307.     db_clientdesc->Packet(&dwID, sizeof(DWORD));
  2308.  
  2309.     char szHint[128];
  2310.     snprintf(szHint, sizeof(szHint), "%s %u", pkItem->GetName(), pkItem->GetCount());
  2311.     if (bMall)
  2312.         LogManager::instance().ItemLog(ch, pkItem, "MALL GET", szHint);
  2313.     else
  2314.         LogManager::instance().ItemLog(ch, pkItem, "SAFEBOX GET", szHint);
  2315. }
  2316.  
  2317. void CInputMain::SafeboxItemMove(LPCHARACTER ch, const char * data)
  2318. {
  2319.     struct command_item_move * pinfo = (struct command_item_move *) data;
  2320.  
  2321.     if (!ch->CanHandleItem())
  2322.         return;
  2323.  
  2324.     if (!ch->GetSafebox())
  2325.         return;
  2326.  
  2327.     ch->GetSafebox()->MoveItem(pinfo->Cell.cell, pinfo->CellTo.cell, pinfo->count);
  2328. }
  2329.  
  2330. // PARTY_JOIN_BUG_FIX
  2331. void CInputMain::PartyInvite(LPCHARACTER ch, const char * c_pData)
  2332. {
  2333.     if (ch->GetArena())
  2334.     {
  2335.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´ë·ÃÀå¿¡¼­ »ç¿ëÇÏ½Ç ¼ö ¾ø½À´Ï´Ù."));
  2336.         return;
  2337.     }
  2338.  
  2339.     TPacketCGPartyInvite * p = (TPacketCGPartyInvite*) c_pData;
  2340.  
  2341.     LPCHARACTER pInvitee = CHARACTER_MANAGER::instance().Find(p->vid);
  2342.  
  2343.     if (!pInvitee || !ch->GetDesc() || !pInvitee->GetDesc())
  2344.     {
  2345.         sys_err("PARTY Cannot find invited character");
  2346.         return;
  2347.     }
  2348.  
  2349.     ch->PartyInvite(pInvitee);
  2350. }
  2351.  
  2352. void CInputMain::PartyInviteAnswer(LPCHARACTER ch, const char * c_pData)
  2353. {
  2354.     if (ch->GetArena())
  2355.     {
  2356.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´ë·ÃÀå¿¡¼­ »ç¿ëÇÏ½Ç ¼ö ¾ø½À´Ï´Ù."));
  2357.         return;
  2358.     }
  2359.  
  2360.     TPacketCGPartyInviteAnswer * p = (TPacketCGPartyInviteAnswer*) c_pData;
  2361.  
  2362.     LPCHARACTER pInviter = CHARACTER_MANAGER::instance().Find(p->leader_vid);
  2363.  
  2364.     // pInviter °¡ ch ¿¡°Ô ÆÄƼ ¿äûÀ» Çß¾ú´Ù.
  2365.  
  2366.     if (!pInviter)
  2367.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ¿äûÀ» ÇÑ Ä³¸¯Å͸¦ ãÀ»¼ö ¾ø½À´Ï´Ù."));
  2368.     else if (!p->accept)
  2369.         pInviter->PartyInviteDeny(ch->GetPlayerID());
  2370.     else
  2371.         pInviter->PartyInviteAccept(ch);
  2372. }
  2373. // END_OF_PARTY_JOIN_BUG_FIX
  2374.  
  2375. void CInputMain::PartySetState(LPCHARACTER ch, const char* c_pData)
  2376. {
  2377.     if (!CPartyManager::instance().IsEnablePCParty())
  2378.     {
  2379.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ¼­¹ö ¹®Á¦·Î ÆÄƼ °ü·Ã 󸮸¦ ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  2380.         return;
  2381.     }
  2382.  
  2383.     TPacketCGPartySetState* p = (TPacketCGPartySetState*) c_pData;
  2384.  
  2385.     if (!ch->GetParty())
  2386.         return;
  2387.  
  2388.     if (ch->GetParty()->GetLeaderPID() != ch->GetPlayerID())
  2389.     {
  2390.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ¸®´õ¸¸ º¯°æÇÒ ¼ö ÀÖ½À´Ï´Ù."));
  2391.         return;
  2392.     }
  2393.  
  2394.     if (!ch->GetParty()->IsMember(p->pid))
  2395.     {
  2396.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> »óŸ¦ º¯°æÇÏ·Á´Â »ç¶÷ÀÌ ÆÄƼ¿øÀÌ ¾Æ´Õ´Ï´Ù."));
  2397.         return;
  2398.     }
  2399.  
  2400.     DWORD pid = p->pid;
  2401.     sys_log(0, "PARTY SetRole pid %d to role %d state %s", pid, p->byRole, p->flag ? "on" : "off");
  2402.  
  2403.     switch (p->byRole)
  2404.     {
  2405.         case PARTY_ROLE_NORMAL:
  2406.             break;
  2407.  
  2408.         case PARTY_ROLE_ATTACKER:
  2409.         case PARTY_ROLE_TANKER:
  2410.         case PARTY_ROLE_BUFFER:
  2411.         case PARTY_ROLE_SKILL_MASTER:
  2412.         case PARTY_ROLE_HASTE:
  2413.         case PARTY_ROLE_DEFENDER:
  2414.             if (ch->GetParty()->SetRole(pid, p->byRole, p->flag))
  2415.             {
  2416.                 TPacketPartyStateChange pack;
  2417.                 pack.dwLeaderPID = ch->GetPlayerID();
  2418.                 pack.dwPID = p->pid;
  2419.                 pack.bRole = p->byRole;
  2420.                 pack.bFlag = p->flag;
  2421.                 db_clientdesc->DBPacket(HEADER_GD_PARTY_STATE_CHANGE, 0, &pack, sizeof(pack));
  2422.             }
  2423.             /* else
  2424.                ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ¾îÅÂÄ¿ ¼³Á¤¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù.")); */
  2425.             break;
  2426.  
  2427.         default:
  2428.             sys_err("wrong byRole in PartySetState Packet name %s state %d", ch->GetName(), p->byRole);
  2429.             break;
  2430.     }
  2431. }
  2432.  
  2433. void CInputMain::PartyRemove(LPCHARACTER ch, const char* c_pData)
  2434. {
  2435.     if (ch->GetArena())
  2436.     {
  2437.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´ë·ÃÀå¿¡¼­ »ç¿ëÇÏ½Ç ¼ö ¾ø½À´Ï´Ù."));
  2438.         return;
  2439.     }
  2440.  
  2441.     if (!CPartyManager::instance().IsEnablePCParty())
  2442.     {
  2443.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ¼­¹ö ¹®Á¦·Î ÆÄƼ °ü·Ã 󸮸¦ ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  2444.         return;
  2445.     }
  2446.  
  2447.     if (ch->GetDungeon())
  2448.     {
  2449.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´øÀü ¾È¿¡¼­´Â ÆÄƼ¿¡¼­ Ãß¹æÇÒ ¼ö ¾ø½À´Ï´Ù."));
  2450.         return;
  2451.     }
  2452.  
  2453.     TPacketCGPartyRemove* p = (TPacketCGPartyRemove*) c_pData;
  2454.  
  2455.     if (!ch->GetParty())
  2456.         return;
  2457.  
  2458.     LPPARTY pParty = ch->GetParty();
  2459.     if (pParty->GetLeaderPID() == ch->GetPlayerID())
  2460.     {
  2461.         if (ch->GetDungeon())
  2462.         {
  2463.             ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´øÁ¯³»¿¡¼­´Â ÆÄƼ¿øÀ» Ãß¹æÇÒ ¼ö ¾ø½À´Ï´Ù."));
  2464.         }
  2465.         else
  2466.         {
  2467.             // Àû·æ¼º¿¡¼­ ÆÄƼÀåÀÌ ´øÁ¯ ¹Û¿¡¼­ ÆÄƼ ÇØ»ê ¸øÇÏ°Ô ¸·ÀÚ
  2468.             if(pParty->IsPartyInDungeon(351))
  2469.             {
  2470.                 ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ>´øÀü ¾È¿¡ ÆÄƼ¿øÀÌ ÀÖ¾î ÆÄÆ¼¸¦ ÇØ»ê ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  2471.                 return;
  2472.             }
  2473.  
  2474.             // leader can remove any member
  2475.             if (p->pid == ch->GetPlayerID() || pParty->GetMemberCount() == 2)
  2476.             {
  2477.                 // party disband
  2478.                 CPartyManager::instance().DeleteParty(pParty);
  2479.             }
  2480.             else
  2481.             {
  2482.                 LPCHARACTER B = CHARACTER_MANAGER::instance().FindByPID(p->pid);
  2483.                 if (B)
  2484.                 {
  2485.                     //pParty->SendPartyRemoveOneToAll(B);
  2486.                     B->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ¿¡¼­ Ãß¹æ´çÇϼ̽À´Ï´Ù."));
  2487.                     //pParty->Unlink(B);
  2488.                     //CPartyManager::instance().SetPartyMember(B->GetPlayerID(), NULL);
  2489.                 }
  2490.                 pParty->Quit(p->pid);
  2491.             }
  2492.         }
  2493.     }
  2494.     else
  2495.     {
  2496.         // otherwise, only remove itself
  2497.         if (p->pid == ch->GetPlayerID())
  2498.         {
  2499.             if (ch->GetDungeon())
  2500.             {
  2501.                 ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´øÁ¯³»¿¡¼­´Â ÆÄƼ¸¦ ³ª°¥ ¼ö ¾ø½À´Ï´Ù."));
  2502.             }
  2503.             else
  2504.             {
  2505.                 if (pParty->GetMemberCount() == 2)
  2506.                 {
  2507.                     // party disband
  2508.                     CPartyManager::instance().DeleteParty(pParty);
  2509.                 }
  2510.                 else
  2511.                 {
  2512.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ¿¡¼­ ³ª°¡¼Ì½À´Ï´Ù."));
  2513.                     //pParty->SendPartyRemoveOneToAll(ch);
  2514.                     pParty->Quit(ch->GetPlayerID());
  2515.                     //pParty->SendPartyRemoveAllToOne(ch);
  2516.                     //CPartyManager::instance().SetPartyMember(ch->GetPlayerID(), NULL);
  2517.                 }
  2518.             }
  2519.         }
  2520.         else
  2521.         {
  2522.             ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ´Ù¸¥ ÆÄƼ¿øÀ» Å»Åð½Ãų ¼ö ¾ø½À´Ï´Ù."));
  2523.         }
  2524.     }
  2525. }
  2526.  
  2527. void CInputMain::AnswerMakeGuild(LPCHARACTER ch, const char* c_pData)
  2528. {
  2529.     TPacketCGAnswerMakeGuild* p = (TPacketCGAnswerMakeGuild*) c_pData;
  2530.  
  2531.     if (ch->GetGold() < 200000)
  2532.         return;
  2533.  
  2534.     // Fix Guild exploit - Júnior Silva
  2535.     if (ch->GetLevel() < 40)
  2536.         return;
  2537.  
  2538.     if (get_global_time() - ch->GetQuestFlag("guild_manage.new_disband_time") <
  2539.             CGuildManager::instance().GetDisbandDelay())
  2540.     {
  2541.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ÇØ»êÇÑ ÈÄ %dÀÏ À̳»¿¡´Â ±æµå¸¦ ¸¸µé ¼ö ¾ø½À´Ï´Ù."),
  2542.                 quest::CQuestManager::instance().GetEventFlag("guild_disband_delay"));
  2543.         return;
  2544.     }
  2545.  
  2546.     if (get_global_time() - ch->GetQuestFlag("guild_manage.new_withdraw_time") <
  2547.             CGuildManager::instance().GetWithdrawDelay())
  2548.     {
  2549.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> Å»ÅðÇÑ ÈÄ %dÀÏ À̳»¿¡´Â ±æµå¸¦ ¸¸µé ¼ö ¾ø½À´Ï´Ù."),
  2550.                 quest::CQuestManager::instance().GetEventFlag("guild_withdraw_delay"));
  2551.         return;
  2552.     }
  2553.  
  2554.     if (ch->GetGuild())
  2555.         return;
  2556.  
  2557.     CGuildManager& gm = CGuildManager::instance();
  2558.  
  2559.     TGuildCreateParameter cp;
  2560.     memset(&cp, 0, sizeof(cp));
  2561.  
  2562.     cp.master = ch;
  2563.     strlcpy(cp.name, p->guild_name, sizeof(cp.name));
  2564.  
  2565.     if (cp.name[0] == 0 || !check_name(cp.name))
  2566.     {
  2567.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ÀûÇÕÇÏÁö ¾ÊÀº ±æµå À̸§ ÀÔ´Ï´Ù."));
  2568.         return;
  2569.     }
  2570.  
  2571.     DWORD dwGuildID = gm.CreateGuild(cp);
  2572.  
  2573.     if (dwGuildID)
  2574.     {
  2575.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> [%s] ±æµå°¡ »ý¼ºµÇ¾ú½À´Ï´Ù."), cp.name);
  2576.  
  2577.         int GuildCreateFee = 200000;
  2578.  
  2579.         ch->PointChange(POINT_GOLD, -GuildCreateFee);
  2580.         DBManager::instance().SendMoneyLog(MONEY_LOG_GUILD, ch->GetPlayerID(), -GuildCreateFee);
  2581.  
  2582.         char Log[128];
  2583.         snprintf(Log, sizeof(Log), "GUILD_NAME %s MASTER %s", cp.name, ch->GetName());
  2584.         LogManager::instance().CharLog(ch, 0, "MAKE_GUILD", Log);
  2585.  
  2586.         ch->RemoveSpecifyItem(GUILD_CREATE_ITEM_VNUM, 1);
  2587.         //ch->SendGuildName(dwGuildID);
  2588.     }
  2589.     else
  2590.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµå »ý¼º¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù."));
  2591. }
  2592.  
  2593. void CInputMain::PartyUseSkill(LPCHARACTER ch, const char* c_pData)
  2594. {
  2595.     TPacketCGPartyUseSkill* p = (TPacketCGPartyUseSkill*) c_pData;
  2596.     if (!ch->GetParty())
  2597.         return;
  2598.  
  2599.     if (ch->GetPlayerID() != ch->GetParty()->GetLeaderPID())
  2600.     {
  2601.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ÆÄƼ ±â¼úÀº ÆÄƼÀ常 »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù."));
  2602.         return;
  2603.     }
  2604.  
  2605.     switch (p->bySkillIndex)
  2606.     {
  2607.         case PARTY_SKILL_HEAL:
  2608.             ch->GetParty()->HealParty();
  2609.             break;
  2610.         case PARTY_SKILL_WARP:
  2611.             {
  2612.                 LPCHARACTER pch = CHARACTER_MANAGER::instance().Find(p->vid);
  2613.                 if (pch)
  2614.                     ch->GetParty()->SummonToLeader(pch->GetPlayerID());
  2615.                 else
  2616.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<ÆÄƼ> ¼ÒȯÇÏ·Á´Â ´ë»óÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù."));
  2617.             }
  2618.             break;
  2619.     }
  2620. }
  2621.  
  2622. void CInputMain::PartyParameter(LPCHARACTER ch, const char * c_pData)
  2623. {
  2624.     TPacketCGPartyParameter * p = (TPacketCGPartyParameter *) c_pData;
  2625.  
  2626.     if (ch->GetParty())
  2627.         ch->GetParty()->SetParameter(p->bDistributeMode);
  2628. }
  2629.  
  2630. size_t GetSubPacketSize(const GUILD_SUBHEADER_CG& header)
  2631. {
  2632.     switch (header)
  2633.     {
  2634.         case GUILD_SUBHEADER_CG_DEPOSIT_MONEY:              return sizeof(int);
  2635.         case GUILD_SUBHEADER_CG_WITHDRAW_MONEY:             return sizeof(int);
  2636.         case GUILD_SUBHEADER_CG_ADD_MEMBER:                 return sizeof(DWORD);
  2637.         case GUILD_SUBHEADER_CG_REMOVE_MEMBER:              return sizeof(DWORD);
  2638.         case GUILD_SUBHEADER_CG_CHANGE_GRADE_NAME:          return 10;
  2639.         case GUILD_SUBHEADER_CG_CHANGE_GRADE_AUTHORITY:     return sizeof(BYTE) + sizeof(BYTE);
  2640.         case GUILD_SUBHEADER_CG_OFFER:                      return sizeof(DWORD);
  2641.         case GUILD_SUBHEADER_CG_CHARGE_GSP:                 return sizeof(int);
  2642.         case GUILD_SUBHEADER_CG_POST_COMMENT:               return 1;
  2643.         case GUILD_SUBHEADER_CG_DELETE_COMMENT:             return sizeof(DWORD);
  2644.         case GUILD_SUBHEADER_CG_REFRESH_COMMENT:            return 0;
  2645.         case GUILD_SUBHEADER_CG_CHANGE_MEMBER_GRADE:        return sizeof(DWORD) + sizeof(BYTE);
  2646.         case GUILD_SUBHEADER_CG_USE_SKILL:                  return sizeof(TPacketCGGuildUseSkill);
  2647.         case GUILD_SUBHEADER_CG_CHANGE_MEMBER_GENERAL:      return sizeof(DWORD) + sizeof(BYTE);
  2648.         case GUILD_SUBHEADER_CG_GUILD_INVITE_ANSWER:        return sizeof(DWORD) + sizeof(BYTE);
  2649.     }
  2650.  
  2651.     return 0;
  2652. }
  2653.  
  2654. int CInputMain::Guild(LPCHARACTER ch, const char * data, size_t uiBytes)
  2655. {
  2656.     if (uiBytes < sizeof(TPacketCGGuild))
  2657.         return -1;
  2658.  
  2659.     const TPacketCGGuild* p = reinterpret_cast<const TPacketCGGuild*>(data);
  2660.     const char* c_pData = data + sizeof(TPacketCGGuild);
  2661.  
  2662.     uiBytes -= sizeof(TPacketCGGuild);
  2663.  
  2664.     const GUILD_SUBHEADER_CG SubHeader = static_cast<GUILD_SUBHEADER_CG>(p->subheader);
  2665.     const size_t SubPacketLen = GetSubPacketSize(SubHeader);
  2666.  
  2667.     if (uiBytes < SubPacketLen)
  2668.     {
  2669.         return -1;
  2670.     }
  2671.  
  2672.     CGuild* pGuild = ch->GetGuild();
  2673.  
  2674.     if (NULL == pGuild)
  2675.     {
  2676.         if (SubHeader != GUILD_SUBHEADER_CG_GUILD_INVITE_ANSWER)
  2677.         {
  2678.             ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµå¿¡ ¼ÓÇØÀÖÁö ¾Ê½À´Ï´Ù."));
  2679.             return SubPacketLen;
  2680.         }
  2681.     }
  2682.  
  2683.     switch (SubHeader)
  2684.     {
  2685.         case GUILD_SUBHEADER_CG_DEPOSIT_MONEY:
  2686.             {
  2687.                 // by mhh : ±æµåÀÚ±ÝÀº ´çºÐ°£ ³ÖÀ» ¼ö ¾ø´Ù.
  2688.                 return SubPacketLen;
  2689.  
  2690.                 const int gold = MIN(*reinterpret_cast<const int*>(c_pData), __deposit_limit());
  2691.  
  2692.                 if (gold < 0)
  2693.                 {
  2694.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> À߸øµÈ ±Ý¾×ÀÔ´Ï´Ù."));
  2695.                     return SubPacketLen;
  2696.                 }
  2697.  
  2698.                 if (ch->GetGold() < gold)
  2699.                 {
  2700.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> °¡Áö°í ÀÖ´Â µ·ÀÌ ºÎÁ·ÇÕ´Ï´Ù."));
  2701.                     return SubPacketLen;
  2702.                 }
  2703.  
  2704.                 pGuild->RequestDepositMoney(ch, gold);
  2705.             }
  2706.             return SubPacketLen;
  2707.  
  2708.         case GUILD_SUBHEADER_CG_WITHDRAW_MONEY:
  2709.             {
  2710.                 // by mhh : ±æµåÀÚ±ÝÀº ´çºÐ°£ »¬ ¼ö ¾ø´Ù.
  2711.                 return SubPacketLen;
  2712.  
  2713.                 const int gold = MIN(*reinterpret_cast<const int*>(c_pData), 500000);
  2714.  
  2715.                 if (gold < 0)
  2716.                 {
  2717.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> À߸øµÈ ±Ý¾×ÀÔ´Ï´Ù."));
  2718.                     return SubPacketLen;
  2719.                 }
  2720.  
  2721.                 pGuild->RequestWithdrawMoney(ch, gold);
  2722.             }
  2723.             return SubPacketLen;
  2724.  
  2725.         case GUILD_SUBHEADER_CG_ADD_MEMBER:
  2726.             {
  2727.                 const DWORD vid = *reinterpret_cast<const DWORD*>(c_pData);
  2728.                 LPCHARACTER newmember = CHARACTER_MANAGER::instance().Find(vid);
  2729.  
  2730.                 if (!newmember)
  2731.                 {
  2732.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±×·¯ÇÑ »ç¶÷À» ãÀ» ¼ö ¾ø½À´Ï´Ù."));
  2733.                     return SubPacketLen;
  2734.                 }
  2735.                
  2736.                 // Fix New guild vulnerability - Júnior Silva
  2737.                 if (!newmember->IsPC())
  2738.                 {
  2739.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±×·¯ÇÑ »ç¶÷À» ãÀ» ¼ö ¾ø½À´Ï´Ù."));
  2740.                     return SubPacketLen;
  2741.                 }
  2742.  
  2743.                 // if (!ch->IsPC())
  2744.                     // return SubPacketLen;
  2745.  
  2746.                 pGuild->Invite(ch, newmember);
  2747.             }
  2748.             return SubPacketLen;
  2749.  
  2750.         case GUILD_SUBHEADER_CG_REMOVE_MEMBER:
  2751.             {
  2752.                 if (pGuild->UnderAnyWar() != 0)
  2753.                 {
  2754.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµåÀü Áß¿¡´Â ±æµå¿øÀ» Å»Åð½Ãų ¼ö ¾ø½À´Ï´Ù."));
  2755.                     return SubPacketLen;
  2756.                 }
  2757.  
  2758.                 const DWORD pid = *reinterpret_cast<const DWORD*>(c_pData);
  2759.                 const TGuildMember* m = pGuild->GetMember(ch->GetPlayerID());
  2760.  
  2761.                 if (NULL == m)
  2762.                     return -1;
  2763.  
  2764.                 LPCHARACTER member = CHARACTER_MANAGER::instance().FindByPID(pid);
  2765.  
  2766.                 if (member)
  2767.                 {
  2768.                     if (member->GetGuild() != pGuild)
  2769.                     {
  2770.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> »ó´ë¹æÀÌ °°Àº ±æµå°¡ ¾Æ´Õ´Ï´Ù."));
  2771.                         return SubPacketLen;
  2772.                     }
  2773.  
  2774.                     if (!pGuild->HasGradeAuth(m->grade, GUILD_AUTH_REMOVE_MEMBER))
  2775.                     {
  2776.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµå¿øÀ» °­Á¦ Å»Åð ½Ãų ±ÇÇÑÀÌ ¾ø½À´Ï´Ù."));
  2777.                         return SubPacketLen;
  2778.                     }
  2779.  
  2780.                     member->SetQuestFlag("guild_manage.new_withdraw_time", get_global_time());
  2781.                     pGuild->RequestRemoveMember(member->GetPlayerID());
  2782.  
  2783.                     if (g_bGuildInviteLimit)
  2784.                     {
  2785.                         DBManager::instance().Query("REPLACE INTO guild_invite_limit VALUES(%d, %d)", pGuild->GetID(), get_global_time());
  2786.                     }
  2787.                 }
  2788.                 else
  2789.                 {
  2790.                     if (!pGuild->HasGradeAuth(m->grade, GUILD_AUTH_REMOVE_MEMBER))
  2791.                     {
  2792.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµå¿øÀ» °­Á¦ Å»Åð ½Ãų ±ÇÇÑÀÌ ¾ø½À´Ï´Ù."));
  2793.                         return SubPacketLen;
  2794.                     }
  2795.  
  2796.                     if (pGuild->RequestRemoveMember(pid))
  2797.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµå¿øÀ» °­Á¦ Å»Åð ½ÃÄ×½À´Ï´Ù."));
  2798.                     else
  2799.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±×·¯ÇÑ »ç¶÷À» ãÀ» ¼ö ¾ø½À´Ï´Ù."));
  2800.                 }
  2801.             }
  2802.             return SubPacketLen;
  2803.  
  2804.         case GUILD_SUBHEADER_CG_CHANGE_GRADE_NAME:
  2805.             {
  2806.                 char gradename[GUILD_GRADE_NAME_MAX_LEN + 1];
  2807.                 strlcpy(gradename, c_pData + 1, sizeof(gradename));
  2808.  
  2809.                 const TGuildMember * m = pGuild->GetMember(ch->GetPlayerID());
  2810.  
  2811.                 if (NULL == m)
  2812.                     return -1;
  2813.  
  2814.                 if (m->grade != GUILD_LEADER_GRADE)
  2815.                 {
  2816.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> Á÷À§ À̸§À» º¯°æÇÒ ±ÇÇÑÀÌ ¾ø½À´Ï´Ù."));
  2817.                 }
  2818.                 else if (*c_pData == GUILD_LEADER_GRADE)
  2819.                 {
  2820.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµåÀåÀÇ Á÷À§ À̸§Àº º¯°æÇÒ ¼ö ¾ø½À´Ï´Ù."));
  2821.                 }
  2822.                 else if (!check_name(gradename))
  2823.                 {
  2824.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ÀûÇÕÇÏÁö ¾ÊÀº Á÷À§ À̸§ ÀÔ´Ï´Ù."));
  2825.                 }
  2826.                 else
  2827.                 {
  2828.                     pGuild->ChangeGradeName(*c_pData, gradename);
  2829.                 }
  2830.             }
  2831.             return SubPacketLen;
  2832.  
  2833.         case GUILD_SUBHEADER_CG_CHANGE_GRADE_AUTHORITY:
  2834.             {
  2835.                 const TGuildMember* m = pGuild->GetMember(ch->GetPlayerID());
  2836.  
  2837.                 if (NULL == m)
  2838.                     return -1;
  2839.  
  2840.                 if (m->grade != GUILD_LEADER_GRADE)
  2841.                 {
  2842.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> Á÷À§ ±ÇÇÑÀ» º¯°æÇÒ ±ÇÇÑÀÌ ¾ø½À´Ï´Ù."));
  2843.                 }
  2844.                 else if (*c_pData == GUILD_LEADER_GRADE)
  2845.                 {
  2846.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµåÀåÀÇ ±ÇÇÑÀº º¯°æÇÒ ¼ö ¾ø½À´Ï´Ù."));
  2847.                 }
  2848.                 else
  2849.                 {
  2850.                     pGuild->ChangeGradeAuth(*c_pData, *(c_pData + 1));
  2851.                 }
  2852.             }
  2853.             return SubPacketLen;
  2854.  
  2855.         case GUILD_SUBHEADER_CG_OFFER:
  2856.             {
  2857.                 DWORD offer = *reinterpret_cast<const DWORD*>(c_pData);
  2858.  
  2859.                 if (pGuild->GetLevel() >= GUILD_MAX_LEVEL)
  2860.                 {
  2861.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµå°¡ ÀÌ¹Ì ÃÖ°í ·¹º§ÀÔ´Ï´Ù."));
  2862.                 }
  2863.                 else
  2864.                 {
  2865.                     offer /= 100;
  2866.                     offer *= 100;
  2867.  
  2868.                     if (pGuild->OfferExp(ch, offer))
  2869.                     {
  2870.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> %uÀÇ °æÇèÄ¡¸¦ ÅõÀÚÇÏ¿´½À´Ï´Ù."), offer);
  2871.                     }
  2872.                     else
  2873.                     {
  2874.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> °æÇèÄ¡ ÅõÀÚ¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù."));
  2875.                     }
  2876.                 }
  2877.             }
  2878.             return SubPacketLen;
  2879.  
  2880.         case GUILD_SUBHEADER_CG_CHARGE_GSP:
  2881.             {
  2882.                 const int offer = *reinterpret_cast<const int*>(c_pData);
  2883.                 const int gold = offer * 100;
  2884.  
  2885.                 if (offer < 0 || gold < offer || gold < 0 || ch->GetGold() < gold)
  2886.                 {
  2887.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> µ·ÀÌ ºÎÁ·ÇÕ´Ï´Ù."));
  2888.                     return SubPacketLen;
  2889.                 }
  2890.  
  2891.                 if (!pGuild->ChargeSP(ch, offer))
  2892.                 {
  2893.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ¿ë½Å·Â ȸº¹¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù."));
  2894.                 }
  2895.             }
  2896.             return SubPacketLen;
  2897.  
  2898.         case GUILD_SUBHEADER_CG_POST_COMMENT:
  2899.             {
  2900.                 const size_t length = *c_pData;
  2901.  
  2902.                 if (length > GUILD_COMMENT_MAX_LEN)
  2903.                 {
  2904.                     // À߸øµÈ ±æÀÌ.. ²÷¾îÁÖÀÚ.
  2905.                     sys_err("POST_COMMENT: %s comment too long (length: %u)", ch->GetName(), length);
  2906.                     ch->GetDesc()->SetPhase(PHASE_CLOSE);
  2907.                     return -1;
  2908.                 }
  2909.  
  2910.                 if (uiBytes < 1 + length)
  2911.                     return -1;
  2912.  
  2913.                 const TGuildMember* m = pGuild->GetMember(ch->GetPlayerID());
  2914.  
  2915.                 if (NULL == m)
  2916.                     return -1;
  2917.  
  2918.                 if (length && !pGuild->HasGradeAuth(m->grade, GUILD_AUTH_NOTICE) && *(c_pData + 1) == '!')
  2919.                 {
  2920.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> °øÁö±ÛÀ» ÀÛ¼ºÇÒ ±ÇÇÑÀÌ ¾ø½À´Ï´Ù."));
  2921.                 }
  2922.                 else
  2923.                 {
  2924.                     std::string str(c_pData + 1, length);
  2925.                     pGuild->AddComment(ch, str);
  2926.                 }
  2927.  
  2928.                 return (1 + length);
  2929.             }
  2930.  
  2931.         case GUILD_SUBHEADER_CG_DELETE_COMMENT:
  2932.             {
  2933.                 const DWORD comment_id = *reinterpret_cast<const DWORD*>(c_pData);
  2934.  
  2935.                 pGuild->DeleteComment(ch, comment_id);
  2936.             }
  2937.             return SubPacketLen;
  2938.  
  2939.         case GUILD_SUBHEADER_CG_REFRESH_COMMENT:
  2940.             pGuild->RefreshComment(ch);
  2941.             return SubPacketLen;
  2942.  
  2943.         case GUILD_SUBHEADER_CG_CHANGE_MEMBER_GRADE:
  2944.             {
  2945.                 const DWORD pid = *reinterpret_cast<const DWORD*>(c_pData);
  2946.                 const BYTE grade = *(c_pData + sizeof(DWORD));
  2947.                 const TGuildMember* m = pGuild->GetMember(ch->GetPlayerID());
  2948.  
  2949.                 if (NULL == m)
  2950.                     return -1;
  2951.  
  2952.                 if (m->grade != GUILD_LEADER_GRADE)
  2953.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> Á÷À§¸¦ º¯°æÇÒ ±ÇÇÑÀÌ ¾ø½À´Ï´Ù."));
  2954.                 else if (ch->GetPlayerID() == pid)
  2955.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµåÀåÀÇ Á÷À§´Â º¯°æÇÒ ¼ö ¾ø½À´Ï´Ù."));
  2956.                 else if (grade == 1)
  2957.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ±æµåÀåÀ¸·Î Á÷À§¸¦ º¯°æÇÒ ¼ö ¾ø½À´Ï´Ù."));
  2958.                 else
  2959.                     pGuild->ChangeMemberGrade(pid, grade);
  2960.             }
  2961.             return SubPacketLen;
  2962.  
  2963.         case GUILD_SUBHEADER_CG_USE_SKILL:
  2964.             {
  2965.                 const TPacketCGGuildUseSkill* p = reinterpret_cast<const TPacketCGGuildUseSkill*>(c_pData);
  2966.  
  2967.                 pGuild->UseSkill(p->dwVnum, ch, p->dwPID);
  2968.             }
  2969.             return SubPacketLen;
  2970.  
  2971.         case GUILD_SUBHEADER_CG_CHANGE_MEMBER_GENERAL:
  2972.             {
  2973.                 const DWORD pid = *reinterpret_cast<const DWORD*>(c_pData);
  2974.                 const BYTE is_general = *(c_pData + sizeof(DWORD));
  2975.                 const TGuildMember* m = pGuild->GetMember(ch->GetPlayerID());
  2976.  
  2977.                 if (NULL == m)
  2978.                     return -1;
  2979.  
  2980.                 if (m->grade != GUILD_LEADER_GRADE)
  2981.                 {
  2982.                     ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> À屺À» ÁöÁ¤ÇÒ ±ÇÇÑÀÌ ¾ø½À´Ï´Ù."));
  2983.                 }
  2984.                 else
  2985.                 {
  2986.                     if (!pGuild->ChangeMemberGeneral(pid, is_general))
  2987.                     {
  2988.                         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<±æµå> ´õÀÌ»ó Àå¼ö¸¦ ÁöÁ¤ÇÒ ¼ö ¾ø½À´Ï´Ù."));
  2989.                     }
  2990.                 }
  2991.             }
  2992.             return SubPacketLen;
  2993.  
  2994.         case GUILD_SUBHEADER_CG_GUILD_INVITE_ANSWER:
  2995.             {
  2996.                 const DWORD guild_id = *reinterpret_cast<const DWORD*>(c_pData);
  2997.                 const BYTE accept = *(c_pData + sizeof(DWORD));
  2998.  
  2999.                 CGuild * g = CGuildManager::instance().FindGuild(guild_id);
  3000.  
  3001.                 if (g)
  3002.                 {
  3003.                     if (accept)
  3004.                         g->InviteAccept(ch);
  3005.                     else
  3006.                         g->InviteDeny(ch->GetPlayerID());
  3007.                 }
  3008.             }
  3009.             return SubPacketLen;
  3010.  
  3011.     }
  3012.  
  3013.     return 0;
  3014. }
  3015.  
  3016. void CInputMain::Fishing(LPCHARACTER ch, const char* c_pData)
  3017. {
  3018.     TPacketCGFishing* p = (TPacketCGFishing*)c_pData;
  3019.     ch->SetRotation(p->dir * 5);
  3020.     ch->fishing();
  3021.     return;
  3022. }
  3023.  
  3024. void CInputMain::ItemGive(LPCHARACTER ch, const char* c_pData)
  3025. {
  3026.     TPacketCGGiveItem* p = (TPacketCGGiveItem*) c_pData;
  3027.     LPCHARACTER to_ch = CHARACTER_MANAGER::instance().Find(p->dwTargetVID);
  3028.  
  3029.     if (to_ch)
  3030.         ch->GiveItem(to_ch, p->ItemPos);
  3031.     else
  3032.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¾ÆÀÌÅÛÀ» °Ç³×ÁÙ ¼ö ¾ø½À´Ï´Ù."));
  3033. }
  3034.  
  3035. void CInputMain::Hack(LPCHARACTER ch, const char * c_pData)
  3036. {
  3037.     TPacketCGHack * p = (TPacketCGHack *) c_pData;
  3038.  
  3039.     char buf[sizeof(p->szBuf)];
  3040.     strlcpy(buf, p->szBuf, sizeof(buf));
  3041.  
  3042.     sys_err("HACK_DETECT: %s %s", ch->GetName(), buf);
  3043.  
  3044.     // ÇöÀç Ŭ¶óÀÌ¾ðÆ®¿¡¼­ ÀÌ ÆÐŶÀ» º¸³»´Â °æ¿ì°¡ ¾øÀ¸¹Ç·Î ¹«Á¶°Ç ²÷µµ·Ï ÇÑ´Ù
  3045.     ch->GetDesc()->SetPhase(PHASE_CLOSE);
  3046. }
  3047.  
  3048. int CInputMain::MyShop(LPCHARACTER ch, const char * c_pData, size_t uiBytes)
  3049. {
  3050.     TPacketCGMyShop * p = (TPacketCGMyShop *) c_pData;
  3051.     int iExtraLen = p->bCount * sizeof(TShopItemTable);
  3052.  
  3053.     if (uiBytes < sizeof(TPacketCGMyShop) + iExtraLen)
  3054.         return -1;
  3055.  
  3056.     if (ch->GetGold() >= GOLD_MAX)
  3057.     {
  3058.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("¼ÒÀ¯ µ·ÀÌ 20¾ï³ÉÀ» ³Ñ¾î °Å·¡¸¦ ÇÛ¼ö°¡ ¾ø½À´Ï´Ù."));
  3059.         sys_log(0, "MyShop ==> OverFlow Gold id %u name %s ", ch->GetPlayerID(), ch->GetName());
  3060.         return (iExtraLen);
  3061.     }
  3062.  
  3063.     if (ch->IsStun() || ch->IsDead())
  3064.         return (iExtraLen);
  3065.  
  3066. #ifdef ENABLE_OFFLINE_SHOP_SYSTEM
  3067.     if (ch->GetExchange() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->IsCubeOpen() || ch->GetOfflineShopOwner())
  3068.     {
  3069.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´Ù¸¥ °Å·¡ÁßÀϰæ¿ì °³ÀλóÁ¡À» ¿­¼ö°¡ ¾ø½À´Ï´Ù."));
  3070.         return (iExtraLen);
  3071.     }
  3072. #else
  3073.     if (ch->GetExchange() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->IsCubeOpen())
  3074.     {
  3075.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´Ù¸¥ °Å·¡ÁßÀϰæ¿ì °³ÀλóÁ¡À» ¿­¼ö°¡ ¾ø½À´Ï´Ù."));
  3076.         return (iExtraLen);
  3077.     }
  3078. #endif
  3079.  
  3080.     sys_log(0, "MyShop count %d", p->bCount);
  3081.     ch->OpenMyShop(p->szSign, (TShopItemTable *) (c_pData + sizeof(TPacketCGMyShop)), p->bCount);
  3082.     return (iExtraLen);
  3083. }
  3084.  
  3085. int CInputMain::MyOfflineShop(LPCHARACTER ch, const char * c_pData, size_t uiBytes)
  3086. {
  3087.     TPacketCGMyOfflineShop * p = (TPacketCGMyOfflineShop *)c_pData;
  3088.     int iExtraLen = p->bCount * sizeof(TShopItemTable);
  3089.  
  3090.     if (uiBytes < sizeof(TPacketCGMyOfflineShop) + iExtraLen)
  3091.         return -1;
  3092.  
  3093.     if (ch->IsStun() || ch->IsDead())
  3094.         return (iExtraLen);
  3095.  
  3096.     if (ch->GetExchange() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->IsCubeOpen() || ch->GetOfflineShopOwner())
  3097.     {
  3098.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("´Ù¸¥ °Å·¡ÁßÀϰæ¿ì °³ÀλóÁ¡À» ¿­¼ö°¡ ¾ø½À´Ï´Ù."));
  3099.         return (iExtraLen);
  3100.     }
  3101.  
  3102.     sys_log(0, "MyOfflineShop count %d", p->bCount);
  3103.     ch->OpenMyOfflineShop(p->szSign, (TShopItemTable *)(c_pData + sizeof(TPacketCGMyOfflineShop)), p->bCount, p->bTime);
  3104.     return (iExtraLen);
  3105. }
  3106.  
  3107. void CInputMain::Refine(LPCHARACTER ch, const char* c_pData)
  3108. {
  3109.     const TPacketCGRefine* p = reinterpret_cast<const TPacketCGRefine*>(c_pData);
  3110.  
  3111. #ifdef ENABLE_OFFLINE_SHOP_SYSTEM
  3112.     if (ch->GetExchange() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->GetMyShop() || ch->IsCubeOpen() || ch->GetOfflineShopOwner())
  3113.     {
  3114.         ch->ChatPacket(CHAT_TYPE_INFO,  LC_TEXT("â°í,°Å·¡Ã¢µîÀÌ ¿­¸° »óÅ¿¡¼­´Â °³·®À» ÇÒ¼ö°¡ ¾ø½À´Ï´Ù"));
  3115.         ch->ClearRefineMode();
  3116.         return;
  3117.     }
  3118. #else
  3119.     if (ch->GetExchange() || ch->IsOpenSafebox() || ch->GetShopOwner() || ch->GetMyShop() || ch->IsCubeOpen())
  3120.     {
  3121.         ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("â°í,°Å·¡Ã¢µîÀÌ ¿­¸° »óÅ¿¡¼­´Â °³·®À» ÇÒ¼ö°¡ ¾ø½À´Ï´Ù"));
  3122.         ch->ClearRefineMode();
  3123.         return;
  3124.     }
  3125. #endif
  3126.  
  3127.     if (p->type == 255)
  3128.     {
  3129.         // DoRefine Cancel
  3130.         ch->ClearRefineMode();
  3131.         return;
  3132.     }
  3133.  
  3134.     if (p->pos >= INVENTORY_MAX_NUM)
  3135.     {
  3136.         ch->ClearRefineMode();
  3137.         return;
  3138.     }
  3139.  
  3140.     LPITEM item = ch->GetInventoryItem(p->pos);
  3141.  
  3142.     if (!item)
  3143.     {
  3144.         ch->ClearRefineMode();
  3145.         return;
  3146.     }
  3147.  
  3148.     ch->SetRefineTime();
  3149.  
  3150.     if (p->type == REFINE_TYPE_NORMAL)
  3151.     {
  3152.         sys_log (0, "refine_type_noraml");
  3153.         ch->DoRefine(item);
  3154.     }
  3155.     else if (p->type == REFINE_TYPE_SCROLL || p->type == REFINE_TYPE_HYUNIRON || p->type == REFINE_TYPE_MUSIN || p->type == REFINE_TYPE_BDRAGON)
  3156.     {
  3157.         sys_log (0, "refine_type_scroll, ...");
  3158.         ch->DoRefineWithScroll(item);
  3159.     }
  3160.     else if (p->type == REFINE_TYPE_MONEY_ONLY)
  3161.     {
  3162.         const LPITEM item = ch->GetInventoryItem(p->pos);
  3163.  
  3164.         if (NULL != item)
  3165.         {
  3166.             if (500 <= item->GetRefineSet())
  3167.             {
  3168.                 LogManager::instance().HackLog("DEVIL_TOWER_REFINE_HACK", ch);
  3169.             }
  3170.             else
  3171.             {
  3172.                 if (ch->GetQuestFlag("deviltower_zone.can_refine"))
  3173.                 {
  3174.                     ch->DoRefine(item, true);
  3175.                     ch->SetQuestFlag("deviltower_zone.can_refine", 0);
  3176.                 }
  3177.                 else
  3178.                 {
  3179.                     ch->ChatPacket(CHAT_TYPE_INFO, "»ç±Í Ÿ¿ö ¿Ï·á º¸»óÀº Çѹø±îÁö »ç¿ë°¡´ÉÇÕ´Ï´Ù.");
  3180.                 }
  3181.             }
  3182.         }
  3183.     }
  3184.  
  3185.     ch->ClearRefineMode();
  3186. }
  3187.  
  3188. int CInputMain::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
  3189. {
  3190.     LPCHARACTER ch;
  3191.  
  3192.     if (!(ch = d->GetCharacter()))
  3193.     {
  3194.         sys_err("no character on desc");
  3195.         d->SetPhase(PHASE_CLOSE);
  3196.         return (0);
  3197.     }
  3198.  
  3199.     int iExtraLen = 0;
  3200.  
  3201.     if (test_server && bHeader != HEADER_CG_MOVE)
  3202.         sys_log(0, "CInputMain::Analyze() ==> Header [%d] ", bHeader);
  3203.  
  3204.     switch (bHeader)
  3205.     {
  3206.         case HEADER_CG_PONG:
  3207.             Pong(d);
  3208.             break;
  3209.  
  3210.         case HEADER_CG_TIME_SYNC:
  3211.             Handshake(d, c_pData);
  3212.             break;
  3213.  
  3214.         case HEADER_CG_CHAT:
  3215.             if (test_server)
  3216.             {
  3217.                 char* pBuf = (char*)c_pData;
  3218.                 sys_log(0, "%s", pBuf + sizeof(TPacketCGChat));
  3219.             }
  3220.  
  3221.             if ((iExtraLen = Chat(ch, c_pData, m_iBufferLeft)) < 0)
  3222.                 return -1;
  3223.             break;
  3224.  
  3225.         case HEADER_CG_WHISPER:
  3226.             if ((iExtraLen = Whisper(ch, c_pData, m_iBufferLeft)) < 0)
  3227.                 return -1;
  3228.             break;
  3229.  
  3230.         case HEADER_CG_MOVE:
  3231.             Move(ch, c_pData);
  3232.  
  3233.             if (g_bCheckClientVersion)
  3234.             {
  3235.                 if (0 != g_stClientVersion.compare(d->GetClientVersion())) // @fixme103 (version > date)
  3236.                 {
  3237.                     ch->ChatPacket(CHAT_TYPE_NOTICE, LC_TEXT("Ŭ¶óÀÌ¾ðÆ® ¹öÀüÀÌ Æ²·Á ·Î±×¾Æ¿ô µË´Ï´Ù. Á¤»óÀûÀ¸·Î ÆÐÄ¡ ÈÄ Á¢¼ÓÇϼ¼¿ä."));
  3238.                     d->DelayedDisconnect(0); // @fixme103 (10);
  3239.                     LogManager::instance().HackLog("VERSION_CONFLICT", d->GetAccountTable().login, ch->GetName(), d->GetHostName());
  3240.                 }
  3241.             }
  3242.             break;
  3243.  
  3244.         case HEADER_CG_CHARACTER_POSITION:
  3245.             Position(ch, c_pData);
  3246.             break;
  3247.  
  3248.         case HEADER_CG_ITEM_USE:
  3249.             if (!ch->IsObserverMode())
  3250.                 ItemUse(ch, c_pData);
  3251.             break;
  3252.  
  3253.         case HEADER_CG_ITEM_DROP:
  3254.             if (!ch->IsObserverMode())
  3255.             {
  3256.                 ItemDrop(ch, c_pData);
  3257.             }
  3258.             break;
  3259.  
  3260.         case HEADER_CG_ITEM_DROP2:
  3261.             if (!ch->IsObserverMode())
  3262.                 ItemDrop2(ch, c_pData);
  3263.             break;
  3264.  
  3265.         case HEADER_CG_ITEM_MOVE:
  3266.             if (!ch->IsObserverMode())
  3267.                 ItemMove(ch, c_pData);
  3268.             break;
  3269.  
  3270.         case HEADER_CG_ITEM_PICKUP:
  3271.             if (!ch->IsObserverMode())
  3272.                 ItemPickup(ch, c_pData);
  3273.             break;
  3274.  
  3275.         case HEADER_CG_ITEM_USE_TO_ITEM:
  3276.             if (!ch->IsObserverMode())
  3277.                 ItemToItem(ch, c_pData);
  3278.             break;
  3279.  
  3280.         case HEADER_CG_ITEM_GIVE:
  3281.             if (!ch->IsObserverMode())
  3282.                 ItemGive(ch, c_pData);
  3283.             break;
  3284.  
  3285.         case HEADER_CG_EXCHANGE:
  3286.             if (!ch->IsObserverMode())
  3287.                 Exchange(ch, c_pData);
  3288.             break;
  3289.  
  3290.         case HEADER_CG_ATTACK:
  3291.         case HEADER_CG_SHOOT:
  3292.             if (!ch->IsObserverMode())
  3293.             {
  3294.                 Attack(ch, bHeader, c_pData);
  3295.             }
  3296.             break;
  3297.  
  3298.         case HEADER_CG_USE_SKILL:
  3299.             if (!ch->IsObserverMode())
  3300.                 UseSkill(ch, c_pData);
  3301.             break;
  3302.  
  3303.         case HEADER_CG_QUICKSLOT_ADD:
  3304.             QuickslotAdd(ch, c_pData);
  3305.             break;
  3306.  
  3307.         case HEADER_CG_QUICKSLOT_DEL:
  3308.             QuickslotDelete(ch, c_pData);
  3309.             break;
  3310.  
  3311.         case HEADER_CG_QUICKSLOT_SWAP:
  3312.             QuickslotSwap(ch, c_pData);
  3313.             break;
  3314.  
  3315.         case HEADER_CG_SHOP:
  3316.             if ((iExtraLen = Shop(ch, c_pData, m_iBufferLeft)) < 0)
  3317.                 return -1;
  3318.             break;
  3319.  
  3320. #ifdef ENABLE_OFFLINE_SHOP_SYSTEM
  3321.         case HEADER_CG_OFFLINE_SHOP:
  3322.             if ((iExtraLen = OfflineShop(ch, c_pData, m_iBufferLeft)) < 0)
  3323.                 return -1;
  3324.             break;
  3325. #endif
  3326.  
  3327.         case HEADER_CG_MESSENGER:
  3328.             if ((iExtraLen = Messenger(ch, c_pData, m_iBufferLeft))<0)
  3329.                 return -1;
  3330.             break;
  3331.  
  3332.         case HEADER_CG_ON_CLICK:
  3333.             OnClick(ch, c_pData);
  3334.             break;
  3335.  
  3336.         case HEADER_CG_SYNC_POSITION:
  3337.             if ((iExtraLen = SyncPosition(ch, c_pData, m_iBufferLeft)) < 0)
  3338.                 return -1;
  3339.             break;
  3340.  
  3341.         case HEADER_CG_ADD_FLY_TARGETING:
  3342.         case HEADER_CG_FLY_TARGETING:
  3343.             FlyTarget(ch, c_pData, bHeader);
  3344.             break;
  3345.  
  3346.         case HEADER_CG_SCRIPT_BUTTON:
  3347.             ScriptButton(ch, c_pData);
  3348.             break;
  3349.  
  3350.             // SCRIPT_SELECT_ITEM
  3351.         case HEADER_CG_SCRIPT_SELECT_ITEM:
  3352.             ScriptSelectItem(ch, c_pData);
  3353.             break;
  3354.             // END_OF_SCRIPT_SELECT_ITEM
  3355.  
  3356.         case HEADER_CG_SCRIPT_ANSWER:
  3357.             ScriptAnswer(ch, c_pData);
  3358.             break;
  3359.  
  3360.         case HEADER_CG_QUEST_INPUT_STRING:
  3361.             QuestInputString(ch, c_pData);
  3362.             break;
  3363.  
  3364.         case HEADER_CG_QUEST_CONFIRM:
  3365.             QuestConfirm(ch, c_pData);
  3366.             break;
  3367.  
  3368.         case HEADER_CG_TARGET:
  3369.             Target(ch, c_pData);
  3370.             break;
  3371.  
  3372.         case HEADER_CG_WARP:
  3373.             Warp(ch, c_pData);
  3374.             break;
  3375.  
  3376.         case HEADER_CG_SAFEBOX_CHECKIN:
  3377.             SafeboxCheckin(ch, c_pData);
  3378.             break;
  3379.  
  3380.         case HEADER_CG_SAFEBOX_CHECKOUT:
  3381.             SafeboxCheckout(ch, c_pData, false);
  3382.             break;
  3383.  
  3384.         case HEADER_CG_SAFEBOX_ITEM_MOVE:
  3385.             SafeboxItemMove(ch, c_pData);
  3386.             break;
  3387.  
  3388.         case HEADER_CG_MALL_CHECKOUT:
  3389.             SafeboxCheckout(ch, c_pData, true);
  3390.             break;
  3391.  
  3392.         case HEADER_CG_PARTY_INVITE:
  3393.             PartyInvite(ch, c_pData);
  3394.             break;
  3395.  
  3396.         case HEADER_CG_PARTY_REMOVE:
  3397.             PartyRemove(ch, c_pData);
  3398.             break;
  3399.  
  3400.         case HEADER_CG_PARTY_INVITE_ANSWER:
  3401.             PartyInviteAnswer(ch, c_pData);
  3402.             break;
  3403.  
  3404.         case HEADER_CG_PARTY_SET_STATE:
  3405.             PartySetState(ch, c_pData);
  3406.             break;
  3407.  
  3408.         case HEADER_CG_PARTY_USE_SKILL:
  3409.             PartyUseSkill(ch, c_pData);
  3410.             break;
  3411.  
  3412.         case HEADER_CG_PARTY_PARAMETER:
  3413.             PartyParameter(ch, c_pData);
  3414.             break;
  3415.  
  3416.         case HEADER_CG_ANSWER_MAKE_GUILD:
  3417. #ifdef ENABLE_NEWGUILDMAKE
  3418.             ch->ChatPacket(CHAT_TYPE_INFO, "<%s> AnswerMakeGuild disabled", __FUNCTION__);
  3419. #else
  3420.             AnswerMakeGuild(ch, c_pData);
  3421. #endif
  3422.             break;
  3423.  
  3424.         case HEADER_CG_GUILD:
  3425.             if ((iExtraLen = Guild(ch, c_pData, m_iBufferLeft)) < 0)
  3426.                 return -1;
  3427.             break;
  3428.  
  3429.         case HEADER_CG_FISHING:
  3430.             Fishing(ch, c_pData);
  3431.             break;
  3432.  
  3433.         case HEADER_CG_HACK:
  3434.             Hack(ch, c_pData);
  3435.             break;
  3436.  
  3437.         case HEADER_CG_MYSHOP:
  3438.             if ((iExtraLen = MyShop(ch, c_pData, m_iBufferLeft)) < 0)
  3439.                 return -1;
  3440.             break;
  3441.  
  3442. #ifdef ENABLE_OFFLINE_SHOP_SYSTEM
  3443.         case HEADER_CG_MY_OFFLINE_SHOP:
  3444.             if ((iExtraLen = MyOfflineShop(ch, c_pData, m_iBufferLeft)) < 0)
  3445.                 return -1;
  3446.             break;
  3447. #endif
  3448.  
  3449.         case HEADER_CG_REFINE:
  3450.             Refine(ch, c_pData);
  3451.             break;
  3452.  
  3453.         case HEADER_CG_CLIENT_VERSION:
  3454.             Version(ch, c_pData);
  3455.             break;
  3456.  
  3457.         case HEADER_CG_HS_ACK:
  3458.             if (isHackShieldEnable)
  3459.             {
  3460.                 CHackShieldManager::instance().VerifyAck(d->GetCharacter(), c_pData);
  3461.             }
  3462.             break;
  3463.  
  3464.         case HEADER_CG_XTRAP_ACK:
  3465.             {
  3466.                 TPacketXTrapCSVerify* p = reinterpret_cast<TPacketXTrapCSVerify*>((void*)c_pData);
  3467.                 CXTrapManager::instance().Verify_CSStep3(d->GetCharacter(), p->bPacketData);
  3468.             }
  3469.             break;
  3470.         case HEADER_CG_DRAGON_SOUL_REFINE:
  3471.             {
  3472.                 TPacketCGDragonSoulRefine* p = reinterpret_cast <TPacketCGDragonSoulRefine*>((void*)c_pData);
  3473.                 switch(p->bSubType)
  3474.                 {
  3475.                 case DS_SUB_HEADER_CLOSE:
  3476.                     ch->DragonSoul_RefineWindow_Close();
  3477.                     break;
  3478.                 case DS_SUB_HEADER_DO_REFINE_GRADE:
  3479.                     {
  3480.                         DSManager::instance().DoRefineGrade(ch, p->ItemGrid);
  3481.                     }
  3482.                     break;
  3483.                 case DS_SUB_HEADER_DO_REFINE_STEP:
  3484.                     {
  3485.                         DSManager::instance().DoRefineStep(ch, p->ItemGrid);
  3486.                     }
  3487.                     break;
  3488.                 case DS_SUB_HEADER_DO_REFINE_STRENGTH:
  3489.                     {
  3490.                         DSManager::instance().DoRefineStrength(ch, p->ItemGrid);
  3491.                     }
  3492.                     break;
  3493.                 }
  3494.             }
  3495.  
  3496.             break;
  3497.     }
  3498.     return (iExtraLen);
  3499. }
  3500.  
  3501. int CInputDead::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
  3502. {
  3503.     LPCHARACTER ch;
  3504.  
  3505.     if (!(ch = d->GetCharacter()))
  3506.     {
  3507.         sys_err("no character on desc");
  3508.         return 0;
  3509.     }
  3510.  
  3511.     int iExtraLen = 0;
  3512.  
  3513.     switch (bHeader)
  3514.     {
  3515.         case HEADER_CG_PONG:
  3516.             Pong(d);
  3517.             break;
  3518.  
  3519.         case HEADER_CG_TIME_SYNC:
  3520.             Handshake(d, c_pData);
  3521.             break;
  3522.  
  3523.         case HEADER_CG_CHAT:
  3524.             if ((iExtraLen = Chat(ch, c_pData, m_iBufferLeft)) < 0)
  3525.                 return -1;
  3526.  
  3527.             break;
  3528.  
  3529.         case HEADER_CG_WHISPER:
  3530.             if ((iExtraLen = Whisper(ch, c_pData, m_iBufferLeft)) < 0)
  3531.                 return -1;
  3532.  
  3533.             break;
  3534.  
  3535.         case HEADER_CG_HACK:
  3536.             Hack(ch, c_pData);
  3537.             break;
  3538.  
  3539.         default:
  3540.             return (0);
  3541.     }
  3542.  
  3543.     return (iExtraLen);
  3544. }
Advertisement
Add Comment
Please, Sign In to add comment