#include "stdafx.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "NPC.h" #include const char* szNPCScriptFileName = "./Script/Game/NPCScript.mcf"; using namespace Quest; CNPC::GoodInfo::GoodInfo() : m_wItemID(0), m_cRace(0), m_cTabPage(0), m_ePreGrade(Item::EquipType::F_GRADE), m_eCurrentGrade(Item::EquipType::F_GRADE) { } CNPC::GoodInfo::GoodInfo(unsigned short wItemID, unsigned char cRace, unsigned char cTabPage) : m_wItemID(wItemID), m_cRace(cRace), m_cTabPage(cTabPage), m_ePreGrade(Item::EquipType::F_GRADE), m_eCurrentGrade(Item::EquipType::F_GRADE) { } class CFindGood : public std::unary_function { public: explicit CFindGood(unsigned short wItemID) : m_wItemID(wItemID) { } bool operator() (CNPC::GoodInfo& goodInfo) { return (m_wItemID == goodInfo.m_wItemID); } private: const unsigned short m_wItemID; }; // NPC ½ºÅ©¸³Æ®¿ë ÇÔ¼ö ¸ñ·Ï namespace NPC { enum NPCFlag { BELONG_TO_CASTLE = (1 << 0), // ¼º ¼ÒÀ¯ NPCÀΰ¡? REPAIRABLE = (1 << 1), // ¼ö¸® °¡´ÉÇÑ NPCÀΰ¡? BLACK_MARKETEER = (1 << 2), // ¾Ï½ÃÀå »óÀÎÀΰ¡? MUST_SELL_WITH_MILEAGE = (1 << 3), // ¸¶Àϸ®Áö·Î ÆÇ¸ÅÇÏ´Â »óÀÎÀΰ¡? MUST_SELL_WITH_SKILLCOUPON = (1 << 4), // ½ºÅ³ ÄíÆùÀ¸·Î ÆÇ¸ÅÇÏ´Â »óÀÎÀΰ¡? DISPLAY_EQUIP = (1 << 5), // Àåºñ¸¦ º¸¿©ÁÖ´Â »óÀÎÀΰ¡? }; void ScriptErrorMessage(const char *msg); void NPCDisplay(int nUID, int nNationType, bool bTestServer, bool bRegularServer, bool bUnifiedServer); void SetNPC(int nZone, int nUID, int nTownID, bool bBelongToCastle, const char *strNpcSkin, const char *strNpcName); void SetPosition(int nUID, float fDirection, float fPosX, float fPosY, float fPosZ); void AddWords(int nUID, const char *strNpcScript); void AddDialog(int nUID, int nPage, int nFlag, const char *strNpcScript); void AddItem(int nUID, int nRaceID, int nTab, int nPage, int nKindItem); void AddZoneMove(int nUID, int nZoneNumber, float fPosX, float fPosY, float fPosZ); void AddQuest(int nNPCID, int nQuestID); void SetDropGrade(int nUID, int nDropType, int nGradeF, int nGradeD, int nGradeC, int nGradeB, int nGradeA); void SetDropBase(int nUID, int nDropType, int nGradeF, int nGradeD, int nGradeC, int nGradeB, int nGradeA); void AddQuestWords(int nUID, int nQuestID, const char* strHelpMessage); void AddPopup(int nUID, int nPopupKind, int nPopupFunction, const char* strPopupString, int nQuestID, int nLimitLevel, int nLimitClass); void AddPopupGuild(int nUID, int nPopupKind, int nPopupFunction, const char* strPopupString, int nQuestID, int nLimitLevel, int nLimitFame); void AddPopupFame(int nUID, int nPopupKind, int nPopupFunction, const char* strPopupString, int nQuestID, int nLimitFame, int nLimitClass); void AddPopupAbility(int nUID, int nPopupKind, int nPopupFunction, const char* strPopupString, int nAbilityID, int nAbilityLV, int nLimitClass); void SetNPCAttribute(int nUID, int nMinimapIconID, int nNation); }; bool CNPC::LoadNPCInfo() { CCreatureManager::GetInstance().DestoryNPCList(); _SE_SetMessageFunction(NPC::ScriptErrorMessage); SCRIPT Script = _SE_Create(szNPCScriptFileName); if (NULL == Script) { return false; } _SE_RegisterFunction(Script, NPC::NPCDisplay, T_VOID, "NPCDisplay", T_INT, T_INT, T_BOOL, T_BOOL, T_BOOL, 0 ) ; _SE_RegisterFunction(Script, NPC::SetNPC, T_VOID, "SetNPC", T_INT, T_INT, T_INT, T_BOOL, T_STRING, T_STRING, 0); _SE_RegisterFunction(Script, NPC::SetPosition, T_VOID, "SetPosition", T_INT, T_FLOAT, T_FLOAT, T_FLOAT, T_FLOAT, 0); _SE_RegisterFunction(Script, NPC::AddWords, T_VOID, "AddWords", T_INT, T_STRING, 0); _SE_RegisterFunction(Script, NPC::AddDialog, T_VOID, "AddDialog", T_INT, T_INT, T_INT, T_STRING, 0); _SE_RegisterFunction(Script, NPC::AddItem, T_VOID, "AddItem", T_INT, T_INT, T_INT, T_INT, T_INT, 0); _SE_RegisterFunction(Script, NPC::AddZoneMove, T_VOID, "AddZoneMove", T_INT, T_INT, T_FLOAT, T_FLOAT, T_FLOAT, 0); _SE_RegisterFunction(Script, NPC::AddQuest, T_VOID, "AddQuest", T_INT, T_INT, 0); _SE_RegisterFunction(Script, NPC::SetDropGrade, T_VOID, "SetDropGrade", T_INT, T_INT, T_INT, T_INT, T_INT, T_INT, T_INT, 0); _SE_RegisterFunction(Script, NPC::SetDropBase, T_VOID, "SetDropBase", T_INT, T_INT, T_INT, T_INT, T_INT, T_INT, T_INT, 0); _SE_RegisterFunction(Script, NPC::AddQuestWords, T_VOID, "AddQuestWords", T_INT, T_INT, T_STRING, 0); _SE_RegisterFunction(Script, NPC::AddPopup, T_VOID, "AddPopup", T_INT, T_INT, T_INT, T_STRING, T_INT, T_INT, T_INT, 0); _SE_RegisterFunction(Script, NPC::AddPopupGuild, T_VOID, "AddPopupGuild", T_INT, T_INT, T_INT, T_STRING, T_INT, T_INT, T_INT, 0); _SE_RegisterFunction(Script, NPC::AddPopupFame, T_VOID, "AddPopupFame", T_INT, T_INT, T_INT, T_STRING, T_INT, T_INT, T_INT, 0); _SE_RegisterFunction(Script, NPC::AddPopupAbility, T_VOID, "AddPopupAbility", T_INT, T_INT, T_INT, T_STRING, T_INT, T_INT, T_INT, 0); _SE_RegisterFunction(Script, NPC::SetNPCAttribute, T_VOID, "SetNPCAttribute", T_INT, T_INT, T_INT, 0); _SE_Execute(Script); _SE_Destroy(Script); CCreatureManager::GetInstance().ProcessAllNPC(std::mem_fun(&CNPC::SortGoods)); CCreatureManager::GetInstance().ProcessAllNPC(std::mem_fun(&CNPC::SortQuests)); return true; } void NPC::ScriptErrorMessage(const char *msg) { MessageBox(NULL, msg, "Script Error", MB_OK); } void NPC::NPCDisplay(int nUID, int nNationType, bool bTestServer, bool bRegularServer, bool bUnifiedServer) { } void NPC::SetNPC(int nZone, int nUID, int nTownID, bool bBelongToCastle, const char *strNpcSkin, const char *strNpcName) { CNPC* lpNPC = new CNPC(nUID, nZone, nTownID, bBelongToCastle); if (!CCreatureManager::GetInstance().AddCreature(lpNPC)) { ERRLOG1(g_Log, "NID:0x%08x NPCµî·Ï¿¡ ½ÇÆÐÇß½À´Ï´Ù.", nUID); delete lpNPC; } } void NPC::SetPosition(int nUID, float fDirection, float fPosX, float fPosY, float fPosZ) { // NPCÀ§Ä¡¸¦ ¼¼ÆÃÇÑ´Ù. CNPC* lpNPC = CCreatureManager::GetInstance().GetNPC(nUID); if (0 != lpNPC) { lpNPC->SetNPCPosition(Position(fPosX, fPosY, fPosZ)); } } void NPC::AddWords(int nUID, const char *strCNPC) { } void NPC::AddDialog(int nUID, int nPage, int nFlag, const char *strCNPC) { } void NPC::AddItem(int nUID, int nRaceID, int nTab, int nPage, int nKindItem) { // ItemÀ» ¼¼ÆÃÇÑ´Ù. CNPC* lpNPC = CCreatureManager::GetInstance().GetNPC(nUID); if (NULL != lpNPC) { CNPC::GoodInfo goodInfo(nKindItem, nRaceID, nTab); lpNPC->AddGoodsToNPC(goodInfo); lpNPC->SetRandomGrade(); } } void NPC::AddZoneMove(int nUID, int nZoneNumber, float fPosX, float fPosY, float fPosZ) { } void NPC::AddQuest(int nNPCID, int nQuestID) { QuestNode* lpQuestNode = CQuestMgr::GetInstance().GetQuestNode(nQuestID); if (lpQuestNode) { CNPC* lpNPC = CCreatureManager::GetInstance().GetNPC(nNPCID); if (NULL != lpNPC) { lpNPC->AddQuestsToNPC(nQuestID); } } else { char szErrMsg[MAX_PATH]; sprintf(szErrMsg, "NPC¿¡ µî·ÏÇÒ Quest°¡ Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù. NPCID:0x%08x QuestID:0x%04x", nNPCID, nQuestID); MessageBox(NULL, szErrMsg, "Script Error", MB_OK); } } void NPC::SetDropGrade(int nUID, int nDropType, int nGradeF, int nGradeD, int nGradeC, int nGradeB, int nGradeA) { // °¢ ±×·¹À̵庰·Î ¾ÆÀÌÅÛÀÌ µîÀåÇÒ È®·üÀ» ¼³Á¤ÇÑ´Ù. CNPC* lpNPC = CCreatureManager::GetInstance().GetNPC(nUID); if (NULL != lpNPC) { lpNPC->SetItemDropGrade(nDropType, nGradeF, nGradeD, nGradeC, nGradeB, nGradeA); } } void NPC::SetDropBase(int nUID, int nDropType, int nGradeF, int nGradeD, int nGradeC, int nGradeB, int nGradeA) { // °¢ ±×·¹À̵庰·Î ºÙ¾î³ª¿Ã ¿É¼ÇÀÇ °¹¼ö(ÃÖ¼Ò°ª)¸¦ ¼³Á¤ÇÑ´Ù. CNPC* lpNPC = CCreatureManager::GetInstance().GetNPC(nUID); if (NULL != lpNPC) { lpNPC->SetItemDropBaseNum(nDropType, nGradeF, nGradeD, nGradeC, nGradeB, nGradeA); } } void NPC::AddQuestWords(int nUID, int nQuestID, const char* strHelpMessage) { } void NPC::AddPopup(int nUID, int nPopupKind, int nPopupFunction, const char* strPopupString, int nQuestID, int nLimitLevel, int nLimitClass) { CNPC* lpNPC = CCreatureManager::GetInstance().GetNPC(nUID); if (NULL != lpNPC) { unsigned long dwFlags = 0; switch (nPopupFunction) { case 11: // Àΰ£ ¹«±â»óÀÎ case 12: // Àΰ£ ¹æ¾î±¸»óÀÎ case 13: // Àΰ£ Àâ»óÀÎ case 14: // Àΰ£ ¹«±â & ¹æ¾î±¸»óÀÎ case 16: // Àΰ£ ¾Ï»ó - ¹«±â»ó case 17: // Àΰ£ ¾Ï»ó - ¹æ¾î±¸»ó case 18: // Àΰ£ ¾Ï»ó - Àâ + ½ºÅ³»ó case 21: // Àΰ£ ´ëÀåÀåÀÌ case 27: // Àΰ£ ¸Þ´Þ»óÀÎ case 28: // Àΰ£ ¸Þ´Þ»óÀÎ ¹«±â»ó case 29: // Àΰ£ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó case 31: // Àΰ£ ¸ðÇè°¡ Æ®·¹ÀÌ³Ê case 32: // Àΰ£ Àü»ç Æ®·¹ÀÌ³Ê case 33: // Àΰ£ ·Î±× Æ®·¹ÀÌ³Ê case 34: // Àΰ£ ¸¶¹ý»ç Æ®·¹ÀÌ³Ê case 35: // Àΰ£ ¼ºÁ÷ÀÚ Æ®·¹ÀÌ³Ê case 42: // Àΰ£ ¹«±¸»óÀÎ case 61: // ¾ÆÄ­ ¹«±â»óÀÎ case 62: // ¾ÆÄ­ ¹æ¾î±¸»óÀÎ case 63: // ¾ÆÄ­ Àâ»óÀÎ case 66: // ¾ÆÄ­ ¾Ï»ó - ¹«±â»ó case 67: // ¾ÆÄ­ ¾Ï»ó - ¹æ¾î±¸»ó case 68: // ¾ÆÄ­ ¾Ï»ó - Àâ + ½ºÅ³»ó case 71: // ¾ÆÄ­ ´ëÀåÀåÀÌ case 77: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ case 78: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹«±â»ó case 79: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó case 81: // ¾ÆÄ­ ºñ±â³Ê Æ®·¹ÀÌ³Ê case 82: // ¾ÆÄ­ ÄĹèÅÏÆ® Æ®·¹ÀÌ³Ê case 83: // ¾ÆÄ­ ¿ÀÇǼ¼ÀÌÅÍ Æ®·¹ÀÌ³Ê case 92: // ¾ÆÄ­ ¹«±¸»óÀÎ dwFlags |= NPC::REPAIRABLE; break; } switch (nPopupFunction) { case 16: // Àΰ£ ¾Ï»ó - ¹«±â»ó case 17: // Àΰ£ ¾Ï»ó - ¹æ¾î±¸»ó case 18: // Àΰ£ ¾Ï»ó - Àâ + ½ºÅ³»ó case 66: // ¾ÆÄ­ ¾Ï»ó - ¹«±â»ó case 67: // ¾ÆÄ­ ¾Ï»ó - ¹æ¾î±¸»ó case 68: // ¾ÆÄ­ ¾Ï»ó - Àâ + ½ºÅ³»ó dwFlags |= NPC::BLACK_MARKETEER; break; } switch (nPopupFunction) { case 27: // Àΰ£ ¸Þ´Þ»óÀÎ case 28: // Àΰ£ ¸Þ´Þ»óÀÎ ¹«±â»ó case 29: // Àΰ£ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó case 77: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ case 78: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹«±â»ó case 79: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó dwFlags |= NPC::MUST_SELL_WITH_MILEAGE; break; } switch (nPopupFunction) { case 123: // ¸ðÇè°¡ »óÀ§ Æ®·¹ÀÌ³Ê case 124: // Àü»ç »óÀ§ Æ®·¹ÀÌ³Ê case 125: // ·Î±× »óÀ§ Æ®·¹ÀÌ³Ê case 126: // ¸¶¹ý»ç »óÀ§ Æ®·¹ÀÌ³Ê case 127: // ¼ºÁ÷ÀÚ »óÀ§ Æ®·¹ÀÌ³Ê case 128: // ºñ±â³Ê »óÀ§ Æ®·¹ÀÌ³Ê case 129: // ÄĹèÅÏÆ® »óÀ§ Æ®·¹ÀÌ³Ê case 130: // ¿ÀÇǼ¼ÀÌÅÍ »óÀ§ Æ®·¹ÀÌ³Ê dwFlags |= NPC::MUST_SELL_WITH_SKILLCOUPON; break; } switch (nPopupFunction) { case 11: // Àΰ£ ¹«±â»óÀÎ case 12: // Àΰ£ ¹æ¾î±¸»óÀÎ case 61: // ¾ÆÄ­ ¹«±â»óÀÎ case 62: // ¾ÆÄ­ ¹æ¾î±¸»óÀÎ dwFlags |= NPC::DISPLAY_EQUIP; break; } lpNPC->SetFlags(dwFlags); } } void NPC::AddPopupGuild(int nUID, int nPopupKind, int nPopupFunction, const char* strPopupString, int nQuestID, int nLimitLevel, int nLimitFame) { CNPC* lpNPC = CCreatureManager::GetInstance().GetNPC(nUID); if (NULL != lpNPC) { unsigned long dwFlags = 0; switch (nPopupFunction) { case 11: // Àΰ£ ¹«±â»óÀÎ case 12: // Àΰ£ ¹æ¾î±¸»óÀÎ case 13: // Àΰ£ Àâ»óÀÎ case 14: // Àΰ£ ¹«±â & ¹æ¾î±¸»óÀÎ case 16: // Àΰ£ ¾Ï»ó - ¹«±â»ó case 17: // Àΰ£ ¾Ï»ó - ¹æ¾î±¸»ó case 18: // Àΰ£ ¾Ï»ó - Àâ + ½ºÅ³»ó case 21: // Àΰ£ ´ëÀåÀåÀÌ case 27: // Àΰ£ ¸Þ´Þ»óÀÎ case 28: // Àΰ£ ¸Þ´Þ»óÀÎ ¹«±â»ó case 29: // Àΰ£ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó case 31: // Àΰ£ ¸ðÇè°¡ Æ®·¹ÀÌ³Ê case 32: // Àΰ£ Àü»ç Æ®·¹ÀÌ³Ê case 33: // Àΰ£ ·Î±× Æ®·¹ÀÌ³Ê case 34: // Àΰ£ ¸¶¹ý»ç Æ®·¹ÀÌ³Ê case 35: // Àΰ£ ¼ºÁ÷ÀÚ Æ®·¹ÀÌ³Ê case 42: // Àΰ£ ¹«±¸»óÀÎ case 61: // ¾ÆÄ­ ¹«±â»óÀÎ case 62: // ¾ÆÄ­ ¹æ¾î±¸»óÀÎ case 63: // ¾ÆÄ­ Àâ»óÀÎ case 66: // ¾ÆÄ­ ¾Ï»ó - ¹«±â»ó case 67: // ¾ÆÄ­ ¾Ï»ó - ¹æ¾î±¸»ó case 68: // ¾ÆÄ­ ¾Ï»ó - Àâ + ½ºÅ³»ó case 71: // ¾ÆÄ­ ´ëÀåÀåÀÌ case 77: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ case 78: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹«±â»ó case 79: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó case 81: // ¾ÆÄ­ ºñ±â³Ê Æ®·¹ÀÌ³Ê case 82: // ¾ÆÄ­ ÄĹèÅÏÆ® Æ®·¹ÀÌ³Ê case 83: // ¾ÆÄ­ ¿ÀÇǼ¼ÀÌÅÍ Æ®·¹ÀÌ³Ê case 92: // ¾ÆÄ­ ¹«±¸»óÀÎ dwFlags |= NPC::REPAIRABLE; break; } switch (nPopupFunction) { case 16: // Àΰ£ ¾Ï»ó - ¹«±â»ó case 17: // Àΰ£ ¾Ï»ó - ¹æ¾î±¸»ó case 18: // Àΰ£ ¾Ï»ó - Àâ + ½ºÅ³»ó case 66: // ¾ÆÄ­ ¾Ï»ó - ¹«±â»ó case 67: // ¾ÆÄ­ ¾Ï»ó - ¹æ¾î±¸»ó case 68: // ¾ÆÄ­ ¾Ï»ó - Àâ + ½ºÅ³»ó dwFlags |= NPC::BLACK_MARKETEER; break; } switch (nPopupFunction) { case 27: // Àΰ£ ¸Þ´Þ»óÀÎ case 28: // Àΰ£ ¸Þ´Þ»óÀÎ ¹«±â»ó case 29: // Àΰ£ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó case 77: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ case 78: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹«±â»ó case 79: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó dwFlags |= NPC::MUST_SELL_WITH_MILEAGE; break; } switch (nPopupFunction) { case 123: // ¸ðÇè°¡ »óÀ§ Æ®·¹ÀÌ³Ê case 124: // Àü»ç »óÀ§ Æ®·¹ÀÌ³Ê case 125: // ·Î±× »óÀ§ Æ®·¹ÀÌ³Ê case 126: // ¸¶¹ý»ç »óÀ§ Æ®·¹ÀÌ³Ê case 127: // ¼ºÁ÷ÀÚ »óÀ§ Æ®·¹ÀÌ³Ê case 128: // ºñ±â³Ê »óÀ§ Æ®·¹ÀÌ³Ê case 129: // ÄĹèÅÏÆ® »óÀ§ Æ®·¹ÀÌ³Ê case 130: // ¿ÀÇǼ¼ÀÌÅÍ »óÀ§ Æ®·¹ÀÌ³Ê dwFlags |= NPC::MUST_SELL_WITH_SKILLCOUPON; break; } switch (nPopupFunction) { case 11: // Àΰ£ ¹«±â»óÀÎ case 12: // Àΰ£ ¹æ¾î±¸»óÀÎ case 61: // ¾ÆÄ­ ¹«±â»óÀÎ case 62: // ¾ÆÄ­ ¹æ¾î±¸»óÀÎ dwFlags |= NPC::DISPLAY_EQUIP; break; } lpNPC->SetFlags(dwFlags); } } void NPC::AddPopupFame(int nUID, int nPopupKind, int nPopupFunction, const char* strPopupString, int nQuestID, int nLimitFame, int nLimitClass) { CNPC* lpNPC = CCreatureManager::GetInstance().GetNPC(nUID); if (NULL != lpNPC) { unsigned long dwFlags = 0; switch (nPopupFunction) { case 11: // Àΰ£ ¹«±â»óÀÎ case 12: // Àΰ£ ¹æ¾î±¸»óÀÎ case 13: // Àΰ£ Àâ»óÀÎ case 14: // Àΰ£ ¹«±â & ¹æ¾î±¸»óÀÎ case 16: // Àΰ£ ¾Ï»ó - ¹«±â»ó case 17: // Àΰ£ ¾Ï»ó - ¹æ¾î±¸»ó case 18: // Àΰ£ ¾Ï»ó - Àâ + ½ºÅ³»ó case 21: // Àΰ£ ´ëÀåÀåÀÌ case 27: // Àΰ£ ¸Þ´Þ»óÀÎ case 28: // Àΰ£ ¸Þ´Þ»óÀÎ ¹«±â»ó case 29: // Àΰ£ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó case 31: // Àΰ£ ¸ðÇè°¡ Æ®·¹ÀÌ³Ê case 32: // Àΰ£ Àü»ç Æ®·¹ÀÌ³Ê case 33: // Àΰ£ ·Î±× Æ®·¹ÀÌ³Ê case 34: // Àΰ£ ¸¶¹ý»ç Æ®·¹ÀÌ³Ê case 35: // Àΰ£ ¼ºÁ÷ÀÚ Æ®·¹ÀÌ³Ê case 42: // Àΰ£ ¹«±¸»óÀÎ case 61: // ¾ÆÄ­ ¹«±â»óÀÎ case 62: // ¾ÆÄ­ ¹æ¾î±¸»óÀÎ case 63: // ¾ÆÄ­ Àâ»óÀÎ case 66: // ¾ÆÄ­ ¾Ï»ó - ¹«±â»ó case 67: // ¾ÆÄ­ ¾Ï»ó - ¹æ¾î±¸»ó case 68: // ¾ÆÄ­ ¾Ï»ó - Àâ + ½ºÅ³»ó case 71: // ¾ÆÄ­ ´ëÀåÀåÀÌ case 77: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ case 78: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹«±â»ó case 79: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó case 81: // ¾ÆÄ­ ºñ±â³Ê Æ®·¹ÀÌ³Ê case 82: // ¾ÆÄ­ ÄĹèÅÏÆ® Æ®·¹ÀÌ³Ê case 83: // ¾ÆÄ­ ¿ÀÇǼ¼ÀÌÅÍ Æ®·¹ÀÌ³Ê case 92: // ¾ÆÄ­ ¹«±¸»óÀÎ dwFlags |= NPC::REPAIRABLE; break; } switch (nPopupFunction) { case 16: // Àΰ£ ¾Ï»ó - ¹«±â»ó case 17: // Àΰ£ ¾Ï»ó - ¹æ¾î±¸»ó case 18: // Àΰ£ ¾Ï»ó - Àâ + ½ºÅ³»ó case 66: // ¾ÆÄ­ ¾Ï»ó - ¹«±â»ó case 67: // ¾ÆÄ­ ¾Ï»ó - ¹æ¾î±¸»ó case 68: // ¾ÆÄ­ ¾Ï»ó - Àâ + ½ºÅ³»ó dwFlags |= NPC::BLACK_MARKETEER; break; } switch (nPopupFunction) { case 27: // Àΰ£ ¸Þ´Þ»óÀÎ case 28: // Àΰ£ ¸Þ´Þ»óÀÎ ¹«±â»ó case 29: // Àΰ£ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó case 77: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ case 78: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹«±â»ó case 79: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó dwFlags |= NPC::MUST_SELL_WITH_MILEAGE; break; } switch (nPopupFunction) { case 123: // ¸ðÇè°¡ »óÀ§ Æ®·¹ÀÌ³Ê case 124: // Àü»ç »óÀ§ Æ®·¹ÀÌ³Ê case 125: // ·Î±× »óÀ§ Æ®·¹ÀÌ³Ê case 126: // ¸¶¹ý»ç »óÀ§ Æ®·¹ÀÌ³Ê case 127: // ¼ºÁ÷ÀÚ »óÀ§ Æ®·¹ÀÌ³Ê case 128: // ºñ±â³Ê »óÀ§ Æ®·¹ÀÌ³Ê case 129: // ÄĹèÅÏÆ® »óÀ§ Æ®·¹ÀÌ³Ê case 130: // ¿ÀÇǼ¼ÀÌÅÍ »óÀ§ Æ®·¹ÀÌ³Ê dwFlags |= NPC::MUST_SELL_WITH_SKILLCOUPON; break; } switch (nPopupFunction) { case 11: // Àΰ£ ¹«±â»óÀÎ case 12: // Àΰ£ ¹æ¾î±¸»óÀÎ case 61: // ¾ÆÄ­ ¹«±â»óÀÎ case 62: // ¾ÆÄ­ ¹æ¾î±¸»óÀÎ dwFlags |= NPC::DISPLAY_EQUIP; break; } lpNPC->SetFlags(dwFlags); } } void NPC::AddPopupAbility(int nUID, int nPopupKind, int nPopupFunction, const char* strPopupString, int nAbilityID, int nAbilityLV, int nLimitClass) { CNPC* lpNPC = CCreatureManager::GetInstance().GetNPC(nUID); if (NULL != lpNPC) { unsigned long dwFlags = 0; switch (nPopupFunction) { case 11: // Àΰ£ ¹«±â»óÀÎ case 12: // Àΰ£ ¹æ¾î±¸»óÀÎ case 13: // Àΰ£ Àâ»óÀÎ case 14: // Àΰ£ ¹«±â & ¹æ¾î±¸»óÀÎ case 16: // Àΰ£ ¾Ï»ó - ¹«±â»ó case 17: // Àΰ£ ¾Ï»ó - ¹æ¾î±¸»ó case 18: // Àΰ£ ¾Ï»ó - Àâ + ½ºÅ³»ó case 21: // Àΰ£ ´ëÀåÀåÀÌ case 27: // Àΰ£ ¸Þ´Þ»óÀÎ case 28: // Àΰ£ ¸Þ´Þ»óÀÎ ¹«±â»ó case 29: // Àΰ£ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó case 31: // Àΰ£ ¸ðÇè°¡ Æ®·¹ÀÌ³Ê case 32: // Àΰ£ Àü»ç Æ®·¹ÀÌ³Ê case 33: // Àΰ£ ·Î±× Æ®·¹ÀÌ³Ê case 34: // Àΰ£ ¸¶¹ý»ç Æ®·¹ÀÌ³Ê case 35: // Àΰ£ ¼ºÁ÷ÀÚ Æ®·¹ÀÌ³Ê case 42: // Àΰ£ ¹«±¸»óÀÎ case 61: // ¾ÆÄ­ ¹«±â»óÀÎ case 62: // ¾ÆÄ­ ¹æ¾î±¸»óÀÎ case 63: // ¾ÆÄ­ Àâ»óÀÎ case 66: // ¾ÆÄ­ ¾Ï»ó - ¹«±â»ó case 67: // ¾ÆÄ­ ¾Ï»ó - ¹æ¾î±¸»ó case 68: // ¾ÆÄ­ ¾Ï»ó - Àâ + ½ºÅ³»ó case 71: // ¾ÆÄ­ ´ëÀåÀåÀÌ case 77: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ case 78: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹«±â»ó case 79: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó case 81: // ¾ÆÄ­ ºñ±â³Ê Æ®·¹ÀÌ³Ê case 82: // ¾ÆÄ­ ÄĹèÅÏÆ® Æ®·¹ÀÌ³Ê case 83: // ¾ÆÄ­ ¿ÀÇǼ¼ÀÌÅÍ Æ®·¹ÀÌ³Ê case 92: // ¾ÆÄ­ ¹«±¸»óÀÎ dwFlags |= NPC::REPAIRABLE; break; } switch (nPopupFunction) { case 16: // Àΰ£ ¾Ï»ó - ¹«±â»ó case 17: // Àΰ£ ¾Ï»ó - ¹æ¾î±¸»ó case 18: // Àΰ£ ¾Ï»ó - Àâ + ½ºÅ³»ó case 66: // ¾ÆÄ­ ¾Ï»ó - ¹«±â»ó case 67: // ¾ÆÄ­ ¾Ï»ó - ¹æ¾î±¸»ó case 68: // ¾ÆÄ­ ¾Ï»ó - Àâ + ½ºÅ³»ó dwFlags |= NPC::BLACK_MARKETEER; break; } switch (nPopupFunction) { case 27: // Àΰ£ ¸Þ´Þ»óÀÎ case 28: // Àΰ£ ¸Þ´Þ»óÀÎ ¹«±â»ó case 29: // Àΰ£ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó case 77: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ case 78: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹«±â»ó case 79: // ¾ÆÄ­ ¸Þ´Þ»óÀÎ ¹æ¾î±¸»ó dwFlags |= NPC::MUST_SELL_WITH_MILEAGE; break; } switch (nPopupFunction) { case 123: // ¸ðÇè°¡ »óÀ§ Æ®·¹ÀÌ³Ê case 124: // Àü»ç »óÀ§ Æ®·¹ÀÌ³Ê case 125: // ·Î±× »óÀ§ Æ®·¹ÀÌ³Ê case 126: // ¸¶¹ý»ç »óÀ§ Æ®·¹ÀÌ³Ê case 127: // ¼ºÁ÷ÀÚ »óÀ§ Æ®·¹ÀÌ³Ê case 128: // ºñ±â³Ê »óÀ§ Æ®·¹ÀÌ³Ê case 129: // ÄĹèÅÏÆ® »óÀ§ Æ®·¹ÀÌ³Ê case 130: // ¿ÀÇǼ¼ÀÌÅÍ »óÀ§ Æ®·¹ÀÌ³Ê dwFlags |= NPC::MUST_SELL_WITH_SKILLCOUPON; break; } switch (nPopupFunction) { case 11: // Àΰ£ ¹«±â»óÀÎ case 12: // Àΰ£ ¹æ¾î±¸»óÀÎ case 61: // ¾ÆÄ­ ¹«±â»óÀÎ case 62: // ¾ÆÄ­ ¹æ¾î±¸»óÀÎ dwFlags |= NPC::DISPLAY_EQUIP; break; } lpNPC->SetFlags(dwFlags); } } void NPC::SetNPCAttribute(int nUID, int nMinimapIconID, int nNation) { CNPC* lpNPC = CCreatureManager::GetInstance().GetNPC(nUID); if (NULL != lpNPC) { lpNPC->SetNation(nNation); } } CNPC::CNPC(unsigned long dwCID, int nZone, int nTownID, bool bBelongToCastle) : CCreature(dwCID), m_nZone(nZone), m_dwTownOrNameID(nTownID), m_dwGID(0), m_cNation(Creature::STATELESS), m_dwFlags(0), m_dwDisplayTime(0) { m_dwFlags |= bBelongToCastle ? NPC::BELONG_TO_CASTLE : 0; if (bBelongToCastle && (nTownID & Castle::CASTLE_BIT)) { m_dwTownOrNameID = ((nTownID & ~Castle::CASTLE_BIT) >> Castle::CASTLE_NAME_BIT_SHIFT); } for (int i = 0; i < Item::EquipType::MAX_OPTION_TYPE; ++i) { for (int j = 0; j < Item::EquipType::MAX_GRADE; ++j) { m_cGradeRate[i][j] = 0; m_cBaseNum[i][j] = 0; } } } CNPC::~CNPC() { } bool CNPC::IsBelongToCastle(void) const { return (m_dwFlags & NPC::BELONG_TO_CASTLE); } unsigned char CNPC::GetNation(void) const { if (0 != m_dwGID) { Guild::CGuild* lpGuild = Guild::CGuildMgr::GetInstance().GetGuild(m_dwGID); if (lpGuild) { return lpGuild->GetNation(); } } return m_cNation; } Item::CItem* CNPC::SellToCharacter(CCharacter *lpCustomer, unsigned short wKindItem, TakeType takeType, Item::CItem* lpRequestItem, unsigned long &dwPrice, unsigned short wCouponID, unsigned short &usError) { unsigned long dwCurrentGold = lpCustomer->GetGold(); unsigned long dwCurrentMileage = lpCustomer->GetMileage(); unsigned char cBaseLevel = lpCustomer->GetStatus().m_nLevel; unsigned char cNum = takeType.m_cNum; float fTax = 0.0f; unsigned long dwTaxIncome = 0; Castle::CCastle* lpCastle = NULL; // ¼º¿¡ ¼ÓÇÑ NPC ¶ó¸é, °Å·¡ ¼¼À² Àû¿ë if (IsBelongToCastle()) { lpCastle = Castle::CCastleMgr::GetInstance().GetCastleByNameID(m_dwTownOrNameID); if (lpCastle) { fTax = lpCastle->GetTax(Castle::TRADE_TAX) / 100.f; } } enum { HACK_BLACK_RANDOM = 0, // ¾Ï½ÃÀå ¿À·ù : ·£´ý¿É¼Ç Àåºñ¸¦ ±¸ÀÔÇÏ°Ô Çß½À´Ï´Ù HACK_BLACK_NOTEXITSITEM, // ¾Ï½ÃÀå ¿À·ù : Á¸ÀçÇÏÁö ¾Ê´Â ¾ÆÀÌÅÛÀÔ´Ï´Ù HACK_MILEAGE_RANDOM, // ¸Þ´Þ»óÁ¡ ¿À·ù : ·£´ý¿É¼Ç Àåºñ¸¦ ±¸ÀÔÇÏ°Ô Çß½À´Ï´Ù HACK_MILEAGE_NOTEXITSITEM, // ¸Þ´Þ»óÁ¡ ¿À·ù : Á¸ÀçÇÏÁö ¾Ê´Â ¾ÆÀÌÅÛÀÔ´Ï´Ù HACK_SHOP_NOTEXITSITEM, // Àåºñ»ó ¿À·ù : Ãë±ÞÇÏÁö ¾Ê´Â ¾ÆÀÌÅÛÀ» ±¸¸ÅÇÕ´Ï´Ù. HACK_SHOP_NOEQUIP, // Àåºñ»ó ¿À·ù : Àåºñ°¡ ¾Æ´Ñ ¾ÆÀÌÅÛÀ» ±¸¸ÅÇÏ·Á ÇÕ´Ï´Ù HACK_SHOP_NOTGRADEITEM, // Àåºñ»ó ¿À·ù : ÆÇ¸ÅÇÏÁö ¾Ê´Â ±×·¹À̵åÀÇ ¾ÆÀÌÅÛÀ» ¿äûÇÏ¿´½À´Ï´Ù HACK_SHOP_NOFGRADEITEM, // Àåºñ»ó ¿À·ù : F±×·¹À̵尡 ¾Æ´Ñ ¾ÆÀÌÅÛÀ» ¿äûÇÏ¿´½À´Ï´Ù HACK_SHOP_SOCKETITEM, // Àåºñ»ó ¿À·ù : ±¸¸ÅÇÒ ¼ö ¾ø´Â ¼ÒÄÏÀÌ ÀÖ´Â ¾ÆÀÌÅÛÀ» ¿äûÇÏ¿´½À´Ï´Ù HACK_SHOP_OVERDURABILITY, // Àåºñ»ó ¿À·ù : ³»±¸µµ°¡ 180 ÀÌ»óÀÎ ¾ÆÀÌÅÛÀÌ »ý¼ºµÇ¾ú½À´Ï´Ù. }; // --------------------------------------------------------------------------------------------- // ¾Ï½ÃÀå if (m_dwFlags & NPC::BLACK_MARKETEER) { // edith 2009.07.20 ¾Ï½ÃÀå¿¡ ·£´ý¿É¼Ç Àåºñ¸¦ »ç°Ô ÆÐŶÀ» º¸³Â´Ù. if(lpRequestItem) { usError = 1; GAMELOG::LogHackBoubt(*lpCustomer, HACK_BLACK_RANDOM, wKindItem, lpRequestItem, usError); ERRLOG1(g_Log, "¾Ï½ÃÀå ¿À·ù : ·£´ý¿É¼Ç Àåºñ¸¦ ±¸ÀÔÇÏ°Ô Çß½À´Ï´Ù. ItemID:%d", wKindItem); return NULL; } const Item::ItemInfo* lpItemInfo = Item::CItemMgr::GetInstance().GetItemInfo(wKindItem); if (NULL == lpItemInfo) { usError = 1; GAMELOG::LogHackBoubt(*lpCustomer, HACK_BLACK_NOTEXITSITEM, wKindItem, NULL, usError); ERRLOG1(g_Log, "¾Ï½ÃÀå ¿À·ù : Á¸ÀçÇÏÁö ¾Ê´Â ¾ÆÀÌÅÛÀÔ´Ï´Ù. ItemID:%d", wKindItem); return NULL; } dwPrice = lpItemInfo->m_DetailData.m_dwBlackPrice * cNum; dwTaxIncome = static_cast(dwPrice * fTax); dwPrice += dwTaxIncome; if (dwPrice > dwCurrentGold) { ERRLOG2(g_Log, "¾Ï½ÃÀå ¿À·ù : µ·ÀÌ ºÎÁ·ÇÕ´Ï´Ù. °¡°Ý:%d, ¼ÒÁö±Ý:%d", dwPrice, dwCurrentGold); return NULL; } Item::CItem* lpItem = Item::CItemFactory::GetInstance().CreateItem(*lpItemInfo); if (NULL == lpItem) { ERRLOG0(g_Log, "¾Ï½ÃÀå ¿À·ù : ¾ÆÀÌÅÛ »ý¼º¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù."); return NULL; } Item::EquipType::OptionType optionType = Item::CItemType::GetInstance().GetOptionType( static_cast(lpItem->GetItemInfo().m_DetailData.m_cItemType)); const unsigned long dwPoint = Math::Random::ComplexRandom( accumulate(m_cGradeRate[optionType], m_cGradeRate[optionType] + Item::EquipType::MAX_GRADE, 0)); unsigned long dwSpace = 0; for (unsigned char cGradeIndex = 0; cGradeIndex < Item::EquipType::MAX_GRADE; ++cGradeIndex) { dwSpace += m_cGradeRate[optionType][cGradeIndex]; if (dwSpace > dwPoint) { Item::CEquipment* lpEquip = Item::CEquipment::DowncastToEquipment(lpItem); if (NULL == lpEquip) { ERRLOG0(g_Log, "¾Ï½ÃÀå ¿À·ù : ¿É¼Ç ¼³Á¤¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù."); return NULL; } int iMagicChancePoint = 0; if(lpCustomer->GetMagicChancePoint() > 0) iMagicChancePoint = (int)(lpCustomer->GetMagicChancePoint()/2); // edith 2009.08.18 ºí·¢¸¶ÄÏÀÌ ·°ÂùÀÇ 50ÇÁ·Î·Î ·°ÂùÅÛ µå¶ø if(lpEquip->AddRandomOption(static_cast(cGradeIndex), m_cBaseNum[optionType][cGradeIndex], iMagicChancePoint)) lpEquip->SetNewEquip(2); else lpEquip->SetNewEquip(); if (dwTaxIncome > 0) { lpCastle->AddTempTaxMoney(Castle::TRADE_TAX, dwTaxIncome); } return lpItem; } } ERRLOG0(g_Log, "¾Ï½ÃÀå ¿À·ù : ¾ÆÀÌÅÛ ±×·¹ÀÌµå ¼³Á¤¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù."); return NULL; } // --------------------------------------------------------------------------------------------- // ¸Þ´Þ»óÁ¡ if (m_dwFlags & NPC::MUST_SELL_WITH_MILEAGE) { // edith 2009.07.20 ¾Ï½ÃÀå¿¡ ·£´ý¿É¼Ç Àåºñ¸¦ »ç°Ô ÆÐŶÀ» º¸³Â´Ù. if(lpRequestItem) { usError = 1; GAMELOG::LogHackBoubt(*lpCustomer, HACK_MILEAGE_RANDOM, wKindItem, lpRequestItem, usError); ERRLOG1(g_Log, "¸Þ´Þ»óÁ¡ ¿À·ù : ·£´ý¿É¼Ç Àåºñ¸¦ ±¸ÀÔÇÏ°Ô Çß½À´Ï´Ù. ItemID:%d", wKindItem); return NULL; } const Item::ItemInfo* lpItemInfo = Item::CItemMgr::GetInstance().GetItemInfo(wKindItem); if (NULL == lpItemInfo) { usError = 1; GAMELOG::LogHackBoubt(*lpCustomer, HACK_MILEAGE_NOTEXITSITEM, wKindItem, NULL, usError); ERRLOG1(g_Log, "¸Þ´Þ»óÁ¡ ¿À·ù : Á¸ÀçÇÏÁö ¾Ê´Â ¾ÆÀÌÅÛÀÔ´Ï´Ù. ItemID:%d", wKindItem); return NULL; } dwPrice = lpItemInfo->m_DetailData.m_dwMedalPrice * cNum; if (dwPrice > dwCurrentMileage) { ERRLOG6(g_Log, "NID:0x%08x °øÇå¸Þ´ÞÀÌ ¸ðÀÚ¶ø´Ï´Ù. ÇöÀç °øÇå¸Þ´ÞÀº %dÀÔ´Ï´Ù. " "(Á¾·ùID:%d, 1°³ °¡°Ý:%d, °³¼ö:%d, Àüü ±Ý¾×:%d)", m_dwCID, dwCurrentMileage, wKindItem, dwPrice, cNum, dwPrice * cNum); return NULL; } bool bStackable = Item::DetailData::STACKABLE == (lpItemInfo->m_DetailData.m_dwFlags & Item::DetailData::STACKABLE); if (false == bStackable || (bStackable && cNum <= lpItemInfo->m_DetailData.m_cMaxDurabilityOrStack)) { Item::CItem* lpItem = Item::CItemFactory::GetInstance().CreateItem(*lpItemInfo); if (NULL != lpItem) { if (true == bStackable) { lpItem->SetNumOrDurability(cNum); } Item::CEquipment* lpEquip = Item::CEquipment::DowncastToEquipment(lpItem); if (NULL != lpEquip) { Item::EquipType::OptionType optionType = Item::CItemType::GetInstance().GetOptionType( static_cast(lpItem->GetItemInfo().m_DetailData.m_cItemType)); const unsigned long dwPoint = Math::Random::ComplexRandom( accumulate(m_cGradeRate[optionType], m_cGradeRate[optionType] + Item::EquipType::MAX_GRADE, 0)); unsigned long dwSpace = 0; for (unsigned char cGradeIndex = 0; cGradeIndex < Item::EquipType::MAX_GRADE; ++cGradeIndex) { dwSpace += m_cGradeRate[optionType][cGradeIndex]; if (dwSpace > dwPoint) { Item::CEquipment* lpEquip = Item::CEquipment::DowncastToEquipment(lpItem); if (NULL == lpEquip) { ERRLOG0(g_Log, "¸Þ´Þ»óÁ¡ ¿À·ù : ¿É¼Ç ¼³Á¤¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù."); return NULL; } lpEquip->AddRandomOption(static_cast(cGradeIndex), m_cBaseNum[optionType][cGradeIndex]); lpEquip->SetNewEquip(); break; } } } } else { ERRLOG1(g_Log, "NID:0x%08x ¾ÆÀÌÅÛ »ý¼º¿¡ ½ÇÆÐÇß½À´Ï´Ù", m_dwCID); } return lpItem; } else { ERRLOG4(g_Log, "NID:0x%08x °¹¼ö°¡ ÀÌ»óÇÕ´Ï´Ù. bStackable:%d, cNum:%d, MaxNumOrDurability:%d", m_dwCID, bStackable, cNum, lpItemInfo->m_DetailData.m_cMaxDurabilityOrStack); } ERRLOG0(g_Log, "¸Þ´Þ»óÁ¡ ¿À·ù : ¾ÆÀÌÅÛ ±×·¹ÀÌµå ¼³Á¤¿¡ ½ÇÆÐÇÏ¿´½À´Ï´Ù."); return NULL; } // --------------------------------------------------------------------------------------------- // Àåºñ»ó if (NULL != lpRequestItem) { CFindGood findGood(lpRequestItem->GetPrototypeID()); std::vector::iterator it = std::find_if(m_Goods.begin(), m_Goods.end(), findGood); if (it == m_Goods.end()) { usError = 1; GAMELOG::LogHackBoubt(*lpCustomer, HACK_SHOP_NOTEXITSITEM, wKindItem, NULL, usError); ERRLOG2(g_Log, "NID:0x%08x Àåºñ»ó ¿À·ù : ÀÌ NPC´Â %dÁ¾·ùÀÇ ¾ÆÀÌÅÛÀ» Ãë±ÞÇÏÁö ¾Ê½À´Ï´Ù.", m_dwCID, lpRequestItem->GetPrototypeID()); DELETE_ITEM(lpRequestItem); return NULL; } Item::CEquipment* lpEquip = Item::CEquipment::DowncastToEquipment(lpRequestItem); if (NULL == lpEquip) { usError = 1; GAMELOG::LogHackBoubt(*lpCustomer, HACK_SHOP_NOEQUIP, wKindItem, NULL, usError); ERRLOG1(g_Log, "Àåºñ»ó ¿À·ù : Àåºñ°¡ ¾Æ´Ñ ¾ÆÀÌÅÛÀ» ±¸¸ÅÇÏ·Á ÇÕ´Ï´Ù. ¾ÆÀÌÅÛID:%d", lpRequestItem->GetPrototypeID()); DELETE_ITEM(lpRequestItem); return NULL; } Item::EquipType::OptionType optionType = Item::CItemType::GetInstance().GetOptionType( static_cast(lpEquip->GetItemInfo().m_DetailData.m_cItemType)); Item::Grade::GradeInfo gradeInfo = lpEquip->GetItemGrade(); GoodInfo& goodInfo = *it; // Àåºñ»óÀÇ ÆÇ¸Å ¹°Ç°ÀÌ ¿ÏÀü ·£´ýÀ¸·Î °áÁ¤µÊ¿¡ µû¶ó, ±×·¹À̵å üũ´Â ÃâÇö ¿©ºÎ¸¸À¸·Î ÇÑÁ¤µË´Ï´Ù. (2004-07-26 by ·Îµò) /* if (goodInfo.m_eCurrentGrade > gradeInfo.m_eItemGrade && goodInfo.m_ePreGrade > gradeInfo.m_eItemGrade) { ERRLOG4(g_Log, "NID:0x%08x Àåºñ»ó ¿À·ù : ¿Ã¹Ù¸£Áö ¾ÊÀº ±×·¹À̵åÀÇ ¾ÆÀÌÅÛÀ» ¿äûÇÏ¿´½À´Ï´Ù. " "GradeÁ¤º¸ - ÀÌÀü:%d, ÇöÀç:%d, ¿äû:%d", m_dwCID, goodInfo.m_ePreGrade, goodInfo.m_eCurrentGrade, gradeInfo.m_eItemGrade); delete lpRequestItem; return NULL; } */ if (0 == m_cGradeRate[optionType][gradeInfo.m_eItemGrade]) { usError = 1; GAMELOG::LogHackBoubt(*lpCustomer, HACK_SHOP_NOTGRADEITEM, wKindItem, lpEquip, usError); ERRLOG2(g_Log, "NID:0x%08x Àåºñ»ó ¿À·ù : ÆÇ¸ÅÇÏÁö ¾Ê´Â ±×·¹À̵åÀÇ ¾ÆÀÌÅÛÀ» ¿äûÇÏ¿´½À´Ï´Ù. " "¿äû ¾ÆÀÌÅÛÀÇ ±×·¹À̵å - %d", m_dwCID, gradeInfo.m_eItemGrade); DELETE_ITEM(lpRequestItem); return NULL; } // edith 2009.07.24 ¸¸¾à Àåºñ°¡ F±×·¹À̵尡 ¾Æ´Ï¸é ±¸¸Å°¡ ºÒ°¡´É Disconnect ½ÃŲ´Ù. if(Item::EquipType::F_GRADE != gradeInfo.m_eItemGrade) { usError = 1; GAMELOG::LogHackBoubt(*lpCustomer, HACK_SHOP_NOFGRADEITEM, wKindItem, lpEquip, usError); ERRLOG2(g_Log, "NID:0x%08x Àåºñ»ó ¿À·ù : F±×·¹À̵尡 ¾Æ´Ñ ¾ÆÀÌÅÛÀ» ¿äûÇÏ¿´½À´Ï´Ù. " "¿äû ¾ÆÀÌÅÛÀÇ ±×·¹À̵å - %d", m_dwCID, gradeInfo.m_eItemGrade); DELETE_ITEM(lpRequestItem); return NULL; } // edith 2009.07.24 ¸¸¾à Àåºñ¿¡ ¼ÒÄÏÀÌ ºÙ¾îÀÖÀ½ ±¸¸Å°¡ ºÒ°¡´É. Disconnect ½ÃŲ´Ù. if( 0 != lpEquip->GetMaxSocketNum() ) { usError = 1; GAMELOG::LogHackBoubt(*lpCustomer, HACK_SHOP_SOCKETITEM, wKindItem, lpEquip, usError); ERRLOG2(g_Log, "NID:0x%08x Àåºñ»ó ¿À·ù : ±¸¸ÅÇÒ ¼ö ¾ø´Â ¼ÒÄÏÀÌ ÀÖ´Â ¾ÆÀÌÅÛÀ» ¿äûÇÏ¿´½À´Ï´Ù. " "¿äû ¾ÆÀÌÅÛÀÇ ±×·¹À̵å - %d", m_dwCID, gradeInfo.m_eItemGrade); DELETE_ITEM(lpRequestItem); return NULL; } // edith 2009.07.24 ¸¸¾à ÀåºñÀÇ ³»±¸µµ°¡ 180ÀÌ»óÀ̸é ÇÙ ÀǽÉÀ¸·Î ·Î±×¸¦ ³²±ä´Ù. if( 180 <= lpEquip->GetMaxNumOrDurability() ) { GAMELOG::LogHackBoubt(*lpCustomer, HACK_SHOP_OVERDURABILITY, wKindItem, lpEquip, usError); } dwPrice = lpRequestItem->GetBuyPrice(); float fd = lpCustomer->GetAbilityValue(Skill::Type::AB_SHOP_MEMBERSHIP); dwPrice -= static_cast((float)dwPrice*fd/100.0f); dwTaxIncome = static_cast(dwPrice * fTax); dwPrice += dwTaxIncome; if (dwPrice > dwCurrentGold) { ERRLOG2(g_Log, "Àåºñ»ó ¿À·ù : µ·ÀÌ ºÎÁ·ÇÕ´Ï´Ù. °¡°Ý:%d, ¼ÒÁö±Ý:%d", dwPrice, dwCurrentGold); DELETE_ITEM(lpRequestItem); return NULL; } if (dwTaxIncome > 0) { lpCastle->AddTempTaxMoney(Castle::TRADE_TAX, dwTaxIncome); } // »óÁ¡¿¡¼­ ÆÄ´Â ¾ÆÀÌÅÛÀº ³»±¸µµ°¡ Ç®ÀÎ »óǰÀ̾î¾ß ÇÑ´Ù. lpRequestItem->SetNumOrDurability(lpRequestItem->GetMaxNumOrDurability()); return lpRequestItem; } // --------------------------------------------------------------------------------------------- // ÀÏ¹Ý »óÁ¡ CFindGood findGood(wKindItem); std::vector::iterator it = std::find_if(m_Goods.begin(), m_Goods.end(), findGood); if (it != m_Goods.end()) { const Item::ItemInfo* lpItemInfo = Item::CItemMgr::GetInstance().GetItemInfo(wKindItem); if (NULL != lpItemInfo) { // ÄíÆù(3,4´Ü°è ½ºÅ³ºÏ)À¸·Î ±¸¸Å if (m_dwFlags & NPC::MUST_SELL_WITH_SKILLCOUPON) { bool bError = false; switch (wCouponID) { case Item::EtcItemID::SKILL_COUPON_3: if (2 != lpItemInfo->m_UseItemInfo.m_usSkill_LockCount) { bError = true; } break; case Item::EtcItemID::SKILL_COUPON_4: if (3 != lpItemInfo->m_UseItemInfo.m_usSkill_LockCount) { bError = true; } break; default: bError = true; break; } if (true == bError) { ERRLOG3(g_Log, "NID:0x%08x ¾Ë¸ÂÀº ÄíÆùÀÌ ¾Æ´Õ´Ï´Ù. ÄíÆùID:%d, ±¸ÀÔ¹°Ç°ID:%d", m_dwCID, wCouponID, wKindItem); return NULL; } } // µ·À¸·Î ±¸¸Å else { dwPrice = lpItemInfo->m_DetailData.m_dwPrice * cNum; float fd = lpCustomer->GetAbilityValue(Skill::Type::AB_SHOP_MEMBERSHIP); dwPrice -= static_cast((float)dwPrice*fd/100.0f); dwTaxIncome = static_cast(dwPrice * fTax); dwPrice += dwTaxIncome; if (dwPrice > dwCurrentGold) { ERRLOG6(g_Log, "NID:0x%08x µ·ÀÌ ¸ðÀÚ¶ø´Ï´Ù. ÇöÀç ¼ÒÁö±ÝÀº %d¿øÀÔ´Ï´Ù. " "(Á¾·ùID:%d, 1°³ °¡°Ý:%d, °³¼ö:%d, Àüü ±Ý¾×:%d)", m_dwCID, dwCurrentGold, wKindItem, dwPrice, cNum, dwPrice * cNum); return NULL; } } bool bStackable = Item::DetailData::STACKABLE == (lpItemInfo->m_DetailData.m_dwFlags & Item::DetailData::STACKABLE); if (false == bStackable || (bStackable && cNum <= lpItemInfo->m_DetailData.m_cMaxDurabilityOrStack)) { Item::CItem* lpItem = Item::CItemFactory::GetInstance().CreateItem(*lpItemInfo); if (NULL != lpItem) { if (true == bStackable) { lpItem->SetNumOrDurability(cNum); } Item::CEquipment* lpEquip = Item::CEquipment::DowncastToEquipment(lpItem); if (NULL != lpEquip) { lpEquip->SetNewEquip(); } if (dwTaxIncome > 0) { lpCastle->AddTempTaxMoney(Castle::TRADE_TAX, dwTaxIncome); } } else { ERRLOG1(g_Log, "NID:0x%08x ¾ÆÀÌÅÛ »ý¼º¿¡ ½ÇÆÐÇß½À´Ï´Ù", m_dwCID); } return lpItem; } else { ERRLOG4(g_Log, "NID:0x%08x °¹¼ö°¡ ÀÌ»óÇÕ´Ï´Ù. bStackable:%d, cNum:%d, MaxNumOrDurability:%d", m_dwCID, bStackable, cNum, lpItemInfo->m_DetailData.m_cMaxDurabilityOrStack); } } else { ERRLOG2(g_Log, "NID:0x%08x ÀÌ NPC´Â ¾ÆÀÌÅÛ ½ºÅ©¸³Æ®¿¡ ¾ø´Â %dÁ¾·ùÀÇ ¾ÆÀÌÅÛÀ» ÆÈ·Á°í ÇÏ¿´½À´Ï´Ù.", m_dwCID, wKindItem); } } else { ERRLOG2(g_Log, "NID:0x%08x ÀÌ NPC´Â %dÁ¾·ùÀÇ ¾ÆÀÌÅÛÀ» Ãë±ÞÇÏÁö ¾Ê½À´Ï´Ù.", m_dwCID, wKindItem); } return NULL; } unsigned long CNPC::RepairItem(Item::CEquipment* lpEquipment, unsigned long& dwCurrentGold) { if (NULL != lpEquipment && (m_dwFlags & NPC::REPAIRABLE)) { unsigned long dwRepairGold = lpEquipment->GetRepairPrice(); // ¼º¿¡ ¼ÓÇÑ NPC ¶ó¸é ¼ö¸® ¼¼À² Àû¿ë if (IsBelongToCastle()) { CCastle* lpCastle = Castle::CCastleMgr::GetInstance().GetCastleByNameID(m_dwTownOrNameID); if (NULL != lpCastle) { const unsigned long dwRepairTax = static_cast(dwRepairGold * (lpCastle->GetTax(Castle::REPAIR_TAX) / 100.0f)); if (dwRepairTax > 0) { lpCastle->AddTempTaxMoney(Castle::REPAIR_TAX, dwRepairTax); dwRepairGold += dwRepairTax; } } } if (dwRepairGold <= dwCurrentGold) { dwCurrentGold -= dwRepairGold; lpEquipment->SetNumOrDurability(lpEquipment->GetMaxNumOrDurability()); return dwRepairGold; } } return 0; } bool CNPC::GetQuest(CCharacter* lpCharacter, unsigned short wQuestID, QuestNode** lppQuestNode) { if (false == std::binary_search(m_Quests.begin(), m_Quests.end(), wQuestID)) { ERRLOG3(g_Log, "CID:0x%08x NPC 0x%08x°¡ °¡Áö°í ÀÖÁö ¾Ê´Â Äù½ºÆ® %d¸¦ ¿äûÇÏ¿´½À´Ï´Ù.", lpCharacter->GetCID(), m_dwCID, wQuestID); return false; } QuestNode* lpQuestNode = CQuestMgr::GetInstance().GetQuestNode(wQuestID); if (NULL == lpQuestNode) { ERRLOG2(g_Log, "NID:0x%08x Äù½ºÆ® ½ºÅ©¸³Æ®¿¡ Á¸ÀçÇÏÁö ¾Ê´Â Äù½ºÆ®ÀÔ´Ï´Ù. QuestID:0x%04x", m_dwCID, wQuestID); return false; } unsigned short wLevel = lpCharacter->GetLevel(); //GetStatus().m_nLevel; if(lpQuestNode->m_wMinLevel != 0 && lpQuestNode->m_wMaxLevel != 0) { if (lpQuestNode->m_wMinLevel > wLevel || lpQuestNode->m_wMaxLevel < wLevel) { ERRLOG3(g_Log, "CID:0x%08x ·¹º§¿¡ ¸ÂÁö ¾Ê´Â Äù½ºÆ®¸¦ ¿äûÇÏ¿´½À´Ï´Ù. QuestID:0x%04x, Level:%d", m_dwCID, wQuestID, wLevel); return false; } } unsigned long wFame = lpCharacter->GetFame(); if(lpQuestNode->m_dwMinFame != 0 && lpQuestNode->m_dwMaxFame != 0) { if (lpQuestNode->m_dwMinFame > wFame || lpQuestNode->m_dwMaxFame < wFame) { ERRLOG3(g_Log, "CID:0x%08x ¸í¼º¿¡ ¸ÂÁö ¾Ê´Â Äù½ºÆ®¸¦ ¿äûÇÏ¿´½À´Ï´Ù. QuestID:0x%04x, Fame:%d", m_dwCID, wQuestID, wFame); return false; } } if (0 == (lpQuestNode->m_dwClass & (0x00000001 << (lpCharacter->GetClass() - 1)))) { ERRLOG3(g_Log, "CID:0x%08x Ŭ·¡½º¿¡ ¸ÂÁö ¾Ê´Â Äù½ºÆ®¸¦ ¿äûÇÏ¿´½À´Ï´Ù. QuestID:0x%04x, Class:%d", m_dwCID, wQuestID, lpCharacter->GetClass()); return false; } // TODO : ¼±Çà Äù½ºÆ® ¿©ºÎ üũ *lppQuestNode = lpQuestNode; return true; } void CNPC::SetItemDropGrade(unsigned char cDropType, unsigned char cGradeF, unsigned char cGradeD, unsigned char cGradeC, unsigned char cGradeB, unsigned char cGradeA) { m_cGradeRate[cDropType][Item::EquipType::F_GRADE] = cGradeF; m_cGradeRate[cDropType][Item::EquipType::D_GRADE] = cGradeD; m_cGradeRate[cDropType][Item::EquipType::C_GRADE] = cGradeC; m_cGradeRate[cDropType][Item::EquipType::B_GRADE] = cGradeB; m_cGradeRate[cDropType][Item::EquipType::A_GRADE] = cGradeA; } void CNPC::SetItemDropBaseNum(unsigned char cDropType, unsigned char cGradeF, unsigned char cGradeD, unsigned char cGradeC, unsigned char cGradeB, unsigned char cGradeA) { m_cBaseNum[cDropType][Item::EquipType::F_GRADE] = cGradeF; m_cBaseNum[cDropType][Item::EquipType::D_GRADE] = cGradeD; m_cBaseNum[cDropType][Item::EquipType::C_GRADE] = cGradeC; m_cBaseNum[cDropType][Item::EquipType::B_GRADE] = cGradeB; m_cBaseNum[cDropType][Item::EquipType::A_GRADE] = cGradeA; } void CNPC::SetRandomGrade(void) { if (m_dwFlags & NPC::DISPLAY_EQUIP) { for (std::vector::iterator it = m_Goods.begin(); it != m_Goods.end(); ++it) { GoodInfo& goodInfo = *it; // Áö³­ ÅÏÀÇ ±×·¹À̵嵵 À¯È¿ÇÏ´Ù. goodInfo.m_ePreGrade = goodInfo.m_eCurrentGrade; const Item::ItemInfo* lpItemInfo = Item::CItemMgr::GetInstance().GetItemInfo(goodInfo.m_wItemID); if (NULL == lpItemInfo) { continue; } Item::EquipType::OptionType optionType = Item::CItemType::GetInstance().GetOptionType( static_cast(lpItemInfo->m_DetailData.m_cItemType)); const unsigned long dwPoint = Math::Random::ComplexRandom( std::accumulate(m_cGradeRate[optionType], m_cGradeRate[optionType] + Item::EquipType::MAX_GRADE, 0)); unsigned long dwSpace = 0; for (unsigned char cIndex = 0; cIndex < Item::EquipType::MAX_GRADE; ++cIndex) { dwSpace += m_cGradeRate[optionType][cIndex]; if (dwSpace > dwPoint) { goodInfo.m_eCurrentGrade = static_cast(cIndex); break; } } } m_dwDisplayTime = GetTickCount(); } } unsigned char CNPC::GetEquipShopInfo(unsigned char cRace, unsigned char cTabPage, unsigned short *aryItemID, unsigned char *aryItemGrade) { unsigned char cNum = 0; unsigned long dwCurrentTime = GetTickCount(); if (dwCurrentTime - m_dwDisplayTime > DISPLAY_CYCLE) { // ÁÖ±âÀûÀ¸·Î ÆÇ¸Å ÀåºñµéÀÇ ±×·¹À̵带 Àç¼³Á¤ÇØÁØ´Ù. SetRandomGrade(); } for (std::vector::iterator it = m_Goods.begin(); it != m_Goods.end(); ++it) { GoodInfo& goodInfo = *it; if (goodInfo.m_cRace == cRace && goodInfo.m_cTabPage == cTabPage) { *aryItemID = goodInfo.m_wItemID; *aryItemGrade = goodInfo.m_eCurrentGrade; ++aryItemID; ++aryItemGrade; ++cNum; } } return cNum; }