UpdateServerPlayer::UpdateServerPlayer (Socket * pSocket ) throw(Error ) //: m_pSocket(pSocket), m_PlayerStatus(USPS_NONE) : m_PlayerStatus(USPS_NONE) { __BEGIN_TRY m_pSocket = pSocket; getCurrentTime(m_ExpireTime); m_ExpireTime.tv_sec += maxIdleSec; Assert(m_pInputStream == NULL); Assert(m_pOutputStream == NULL); try { // 소켓입력스트림은 그대로 생성해준다. m_pInputStream = new SocketInputStream(m_pSocket, clientBufferSize); } catch (Error& t) { filelog("updateServerPlayerBUG.txt", "%s", t.toString().c_str()); throw; } catch (Throwable& t) { filelog("updateServerPlayerBUG.txt", "%s", t.toString().c_str()); } __END_CATCH }
void startConnMgrWatch(HWND hWnd){ HRESULT hr; hEdit=hWnd; if(WM_CM_STATUS_CHANGE==WM_USER+1234){ // do only once, if 1234 then not registered WM_CM_STATUS_CHANGE = RegisterWindowMessage( CONNMGR_STATUS_CHANGE_NOTIFICATION_MSG ); if(WM_CM_STATUS_CHANGE==0) //failed { logMsg(L"RegisterWindowMessage failed: %i\n", GetLastError()); } else logMsg(L"RegisterWindowMessage OK: id=%08x\n", WM_CM_STATUS_CHANGE); //DEBUGMSG(1, (L"RegisterWindowMessage =0x%x.\r\n", WM_CM_STATUS_CHANGE)); //logMsg(L"RegisterWindowMessage =0x%x.\r\n", WM_CM_STATUS_CHANGE); } // after you registered for the CONNMGR_STATUS_CHANGE_NOTIFICATION_MSG and got a constant you can watch for changes hr = ConnMgrRegisterForStatusChangeNotification(TRUE, hWnd); if(hr==S_OK) filelog(L"ConnMgrRegisterForStatusChangeNotification OK\n"); else if(hr==E_HANDLE) filelog(L"ConnMgrRegisterForStatusChangeNotification Invalid handle!\n"); else if(hr==E_ACCESSDENIED) filelog(L"ConnMgrRegisterForStatusChangeNotification Access denied!\n"); else filelog(L"ConnMgrRegisterForStatusChangeNotification Unknown error code: %i!\n", hr); return; }
void CGSMSSendHandler::execute (CGSMSSend* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ Assert(pPacket != NULL); Assert(pPlayer != NULL); GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Assert(pGamePlayer != NULL); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pGamePlayer->getCreature()); Assert(pPC != NULL); filelog("SMS.log", "[%s:%s] %s", pGamePlayer->getID().c_str(), pPC->getName().c_str(), pPacket->toString().c_str()); GCAddressListVerify gcVerify; if (pPC->getSMSCharge() < pPacket->getNumbersList().size() ) { filelog("SMS.log", "[%s:%s] Charge가 모자랍니다.", pGamePlayer->getID().c_str(), pPC->getName().c_str()); gcVerify.setCode(GCAddressListVerify::SMS_SEND_FAIL); gcVerify.setParameter(GCAddressListVerify::SMS_SEND_FAIL_NOT_ENOUGH_CHARGE); pGamePlayer->sendPacket(&gcVerify); return; } pPC->setSMSCharge(pPC->getSMSCharge() - pPacket->getNumbersList().size()); char buffer[100]; sprintf(buffer, "SMSCharge=%u", pPC->getSMSCharge()); pPC->tinysave(buffer); list<string>::const_iterator itr = pPacket->getNumbersList().begin(); list<string>::const_iterator endItr = pPacket->getNumbersList().end(); for (; itr != endItr ; ++itr ) { if (SMSServiceThread::Instance().isValidNumber(*itr ) ) { SMSMessage* pMsg = new SMSMessage(pPC->getName(), *itr, pPacket->getCallerNumber(), pPacket->getMessage()); SMSServiceThread::Instance().pushMessage(pMsg); } } gcVerify.setCode(GCAddressListVerify::SMS_SEND_OK); gcVerify.setParameter(pPC->getSMSCharge()); pGamePlayer->sendPacket(&gcVerify); #endif __END_DEBUG_EX __END_CATCH }
// 실행 함수 void PKTConnectAcceptHandler::execute(MPlayer* pPlayer, MPacket* pPacket ) { //cout << "--------------------------------------------------" << endl; //cout << "RECV [" << pPlayer->getJob()->getName() << "] ConnectAccept" << endl; //cout << "--------------------------------------------------" << endl; filelog(MOFUS_LOG_FILE, "RECV [%s] ConnectAccept", pPlayer->getJob()->getName().c_str()); filelog(MOFUS_PACKET_FILE, "RECV : [%s] %s", pPlayer->getJob()->getName().c_str(), pPacket->toString().c_str()); // 유저 인포를 요청. 파워포인트 가져오기 pPlayer->sendUserInfo(); }
void CGCrashReportHandler::execute (CGCrashReport* pPacket , Player* pPlayer) throw(ProtocolException, Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ Assert(pPacket != NULL); Assert(pPlayer != NULL); GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Creature* pCreature = pGamePlayer->getCreature(); Statement* pStmt = NULL; try { BEGIN_DB { pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement(); pStmt->executeQuery("INSERT INTO `CrashReportLog` (`PlayerID`, `Name`, `ReportTime`, `ExecutableTime`, `Version`, `Address`, `Message`, `OS`, `CallStack`) VALUES ('%s', '%s', now(), '%s', %u, '%s', '%s', '%s', '%s')", pGamePlayer->getID().c_str(), pCreature->getName().c_str(), pPacket->getExecutableTime().c_str(), pPacket->getVersion(), pPacket->getAddress().c_str(), pPacket->getMessage().c_str(), pPacket->getOS().c_str(), pPacket->getCallStack().c_str()); SAFE_DELETE(pStmt); } END_DB(pStmt) // 누가 이상한거 날리면 무시하자 } catch(...) { filelog("CrashReport.log", "%s", pPacket->toString().c_str()); } #endif // __GAME_SERVER__ __END_DEBUG_EX __END_CATCH }
bool GuildUnion::removeGuild(GuildID_t gID ) throw(Error) { if (m_MasterGuildID == gID ) return false; list<GuildID_t>::iterator itr = findGuildItr(gID); if (itr == m_Guilds.end() ) return false; m_Guilds.erase(itr); Statement* pStmt = NULL; BEGIN_DB { pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement(); pStmt->executeQuery("DELETE FROM GuildUnionMember WHERE UnionID = %u and OwnerGuildID = %u", m_UnionID, gID); if (pStmt->getAffectedRowCount() < 1 ) { filelog("GuildUnion.log", "[%u:%u] 탈퇴하려는데 해당 레코드가 없습니다.", m_UnionID, gID); } SAFE_DELETE(pStmt); } END_DB(pStmt); return true; }
////////////////////////////////////////////////////////////////////////////// /// \brief /// \param fmt /// \param ... ////////////////////////////////////////////////////////////////////////////// void XMLUtil::filelog(char* fmt, ...) { ofstream file(XML_ERROR_FILENAME, ios::out | ios::app); if (file.is_open()) { va_list valist; va_start(valist, fmt); char message_buffer[30000] = {0, }; int nchars = vsnprintf(message_buffer, 30000, fmt, valist); if (nchars == -1 || nchars > 30000) { filelog(NULL, "filelog buffer overflow!"); throw("filelog() : more buffer size needed for log"); } va_end(valist); time_t now = time(0); char time_buffer[256] = {0, }; sprintf(time_buffer, "%s : ", ctime(&now)); file.write(time_buffer, (streamsize)strlen(time_buffer)); file.write(message_buffer, (streamsize)strlen(message_buffer)); file.write("\n", (streamsize)strlen("\n")); } }
void finish(struct transfer *transfer, struct trdata *data) { filelog("finish %ls at %zi, total %zi", transfer->path, transfer->curpos, transfer->curpos - data->startpos); #ifdef HAVE_XATTR if(confgetint("reqstat", "xa")) xainc(transfer->path, "user.dc-bytes", transfer->curpos - data->startpos); #endif }
// 실행 함수 void PKTUserInfoHandler::execute(GameServerPlayer* pPlayer, MPacket* pPacket ) { //cout << "--------------------------------------------------" << endl; //cout << "RECV UserInfo" << endl; //cout << "--------------------------------------------------" << endl; filelog(MOFUS_LOG_FILE, "RECV UserInfo"); filelog(MOFUS_PACKET_FILE, "RECV : %s", pPacket->toString().c_str()); PKTPowerPoint pkt; strcpy(pkt.sCharName, "슬11"); pkt.nPowerPoint = 300; pkt.nContinue = rand() % 2; pkt.nOnGameCode = 1; //cout << "sending PowerPoint : " << endl << pkt.toString() << endl; pPlayer->sendPacket(&pkt); }
void request(struct transfer *transfer, struct trdata *data) { filelog("request %ls", transfer->path); #ifdef HAVE_XATTR if(confgetint("reqstat", "xa")) xainc(transfer->path, "user.dc-req", 1); #endif }
void start(struct transfer *transfer, struct trdata *data) { filelog("start %ls at %zi", transfer->path, data->startpos); #ifdef HAVE_XATTR if(confgetint("reqstat", "xa")) xainc(transfer->path, "user.dc-started", 1); #endif }
// 패킷의 크기를 반환한다. MPacketSize_t MPacketManager::getPacketSize(MPacketID_t ID ) const { if (ID < 0 || ID >= PTC_SEND_MAX ) { filelog(MOFUS_ERROR_FILE, "MPacketManager::createPacket() out of ID"); Assert(false); } return m_pImpl->pCreators[ID]->getSize(); }
// 패킷을 실행한다. void MPacketManager::execute(GameServerPlayer* pPlayer, MPacket* pPacket ) { Assert(pPlayer != NULL); Assert(pPacket != NULL); MPacketID_t ID = pPacket->getID(); if (ID < 0 || ID >= PTC_SEND_MAX ) { filelog(MOFUS_ERROR_FILE, "MPacketManager::createPacket() out of ID"); Assert(false); } if (m_pImpl->pHandlers[ID] == NULL ) { filelog(MOFUS_ERROR_FILE, "MPacketManager::execute() Handler is NULL"); Assert(false); } m_pImpl->pHandlers[ID]->execute(pPlayer, pPacket); }
////////////////////////////////////////////////////////////////////////////// // 머리위에 GlobalChat 스트링을 띄울때 사용하는 패킷이다. // 이 크리처를 볼 수 있는 모든 플레이어에게 브로드캐스트한다. // 일단은 현재 존의 모든 플레이어(또는 전체 플레이어)에게 // GCGlobalChat 패킷을 브로드캐스트한다. ////////////////////////////////////////////////////////////////////////////// void CGGlobalChatHandler::execute (CGGlobalChat* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ Assert(pPacket != NULL); Assert(pPlayer != NULL); GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); if (pGamePlayer->getPlayerStatus() == GPS_NORMAL) { if (pGamePlayer->isPenaltyFlag(PENALTY_TYPE_MUTE)) { return; } Creature* pCreature = pGamePlayer->getCreature(); Assert(pCreature != NULL); // 서버에서 클라이언트로 전송하므로 GC- 패킷을 사용해야 한다. GCGlobalChat gcGlobalChat; uint i = pPacket->getMessage().find_first_of('*' , 0); if (i == 0) return; // text color setting gcGlobalChat.setColor(pPacket->getColor()); // 크리처 이름과 메시지를 패킷에 대입한다. StringStream msg; msg << pCreature->getName() << " " << pPacket->getMessage(); gcGlobalChat.setMessage(msg.toString()); gcGlobalChat.setRace(pCreature->getRace()); // 주변 PC들에게 브로드캐스트한다. pCreature->getZone()->broadcastPacket(&gcGlobalChat , pCreature); // 채팅 로그를 남긴다. by sigi. 2002.10.30 if (LogNameManager::getInstance().isExist(pCreature->getName() )) { filelog("chatLog.txt", "[Global] %s> %s", pCreature->getName().c_str(), pPacket->getMessage().c_str()); } } #endif __END_DEBUG_EX __END_CATCH }
void NetmarbleGuildRegisterThread::run() throw(Error) { __BEGIN_DEBUG string host = g_pConfig->getProperty("DB_HOST"); string db = g_pConfig->getProperty("DB_DB"); string user = g_pConfig->getProperty("DB_USER"); string password = g_pConfig->getProperty("DB_PASSWORD"); Connection* pConnection = new Connection(host, db, user, password); g_pDatabaseManager->addConnection((int)Thread::self(), pConnection); //cout << "******************************************************" << endl; //cout << " THREAD CONNECT DB " << endl; //cout << "******************************************************" << endl; // create PLAYER Database Connection string dist_host = g_pConfig->getProperty("UI_DB_HOST"); string dist_db = "DARKEDEN"; string dist_user = g_pConfig->getProperty("UI_DB_USER"); string dist_password = g_pConfig->getProperty("UI_DB_PASSWORD"); Connection* pDistConnection = new Connection(dist_host, dist_db, dist_user, dist_password); g_pDatabaseManager->addDistConnection(((int)Thread::self()), pDistConnection); //cout << "******************************************************" << endl; //cout << " THREAD CONNECT UIIRIBUTION DB " << endl << " TID Number = " << (int)Thread::self() << endl; //cout << "******************************************************" << endl; Py_Initialize(); PyRun_SimpleString("import httdlib, urllib"); try { Timeval dummyQueryTime; getCurrentTime(dummyQueryTime); while (true) { // ±æµå µî·Ï registerGuild(); // for context switch usleep(100); } } catch (Throwable& t) { filelog("NetmarbleGuildRegisterThread.log", "%s", t.toString().c_str()); throw; } Py_Finalize(); __END_DEBUG }
// 패킷 생성자를 추가한다. void MPacketManager::IMPL::addCreator(MPacket* pPacket ) { Assert(pPacket != NULL); // 중복 검사 if (pCreators[pPacket->getID()] != NULL ) { filelog(MOFUS_ERROR_FILE, "MPacketManager::IMPL::addCreator() dup creator"); Assert(false); } // 생성자를 추가한다. pCreators[pPacket->getID()] = pPacket; }
// 패킷 핸들러를 추가한다. void MPacketManager::IMPL::addHandler(MPacketHandler* pHandler ) { Assert(pHandler != NULL); // 중복 검사 if (pHandlers[pHandler->getID()] != NULL ) { filelog(MOFUS_ERROR_FILE, "MPacketManager::IMPL::addHandler() dup handler"); Assert(false); } // 핸들러를 추가한다. pHandlers[pHandler->getID()] = pHandler; }
////////////////////////////////////////////////////////////////////////////// // 생성자 // 마스크를 초기화한다. ////////////////////////////////////////////////////////////////////////////// IceWave::IceWave() throw() { __BEGIN_TRY int index=0; for (int i=-3; i<=3; ++i ) { for (int j=-3; j<=3; ++j ) { filelog("IceWave.log", "%d:(%d,%d)", index, i, j); m_pIceWaveMask[index++].set(i, j); } } for (int i=0; i<8; ++i ) { for (int j=1; j<=2; ++j ) { int ox = dirMoveMask[i].x * j * 3 + dirMoveMask[i].x * 2; int oy = dirMoveMask[i].y * j * 3 + dirMoveMask[i].y * 2; for (int k=-1; k<=1; ++k ) { for (int l=-1; l<=1; ++l ) { filelog("IceWave.log", "%d:(%d,%d)", index, ox+k, oy+l); m_pIceWaveMask[index++].set(ox+k, oy+l); } } } } __END_CATCH }
GQuestElement::ResultType GQuestStatus::checkElements(GQuestInfo::ElementType type) { switch (m_pGQuestInfo->getCheckType(type) ) { case GQuestInfo::SEQUENCE: return checkElementsSEQ(type); case GQuestInfo::AND: return checkElementsAND(type); case GQuestInfo::OR: return checkElementsOR(type); default: filelog("GQuestBug.log", "%u - GQuestStatus::checkElements(%u) : Invalid checkType : %d", m_pGQuestInfo->getQuestID(), type, m_pGQuestInfo->getCheckType(type)); Assert(false); } return GQuestElement::FAIL; }
////////////////////////////////////////////////////////////////////////////// // Destructor ////////////////////////////////////////////////////////////////////////////// Creature::~Creature () throw() { __BEGIN_TRY m_pPlayer = NULL; // delete´Â ¿ÜºÎ¿¡¼ ÇÑ´Ù. SAFE_DELETE(m_pEffectManager); if (m_CClass == CREATURE_CLASS_SLAYER || m_CClass == CREATURE_CLASS_VAMPIRE ) { if (!m_bDeriveDestructed ) { filelog("destructor.log", "Name : %s Class : %d value : %d" , m_Owner.c_str(), (int)m_CClass, m_Value); } } __END_CATCH }
void logMsg (const wchar_t *fmt, ...) { va_list vl; va_start(vl,fmt); wchar_t bufW[1024]; // to bad CE hasn't got wvnsprintf wvsprintf(bufW,fmt,vl); char bufOutA[512]; filelog(L"%s", bufW); //convert to char WideCharToMultiByte(CP_ACP,0,bufW,-1,bufOutA,400, NULL, NULL); if(hEdit){ int iLen = PostMessage(hEdit, WM_GETTEXTLENGTH, 0, 0); iLen+=wcslen(bufW); if(iLen>32000) { //clear text PostMessage(hEdit,WM_SETTEXT,0,0); iLen=wcslen(bufW); PostMessage(hEdit, WM_SETTEXT, NULL, (LPARAM)bufW); } else{ TCHAR* buffer=(TCHAR*)calloc((2+iLen), sizeof(TCHAR)); PostMessage(hEdit,WM_GETTEXT, iLen * sizeof(TCHAR), reinterpret_cast<LPARAM>(buffer)); wcscat(buffer, bufW); //DEBUGMSG(1, (buffer)); //addText(hEdit, bufW); PostMessage(hEdit, WM_SETTEXT, NULL, (LPARAM)buffer); free (buffer); } PostMessage(hEdit, EM_SETSEL, 0, MAKELONG(0xffff,0xffff)); PostMessage(hEdit, EM_SCROLLCARET, 0,0); UpdateWindow(hEdit); } #ifdef DEBUG DEBUGMSG(1, (bufW)); #else RETAILMSG(1, (bufW)); #endif }
void dumpConnections(HWND hWnd){ hEdit=hWnd; HANDLE hConnMgrReady = ConnMgrApiReadyEvent(); DWORD dwWait = WaitForSingleObject(hConnMgrReady, 3000); switch (dwWait){ case WAIT_OBJECT_0: break; case WAIT_FAILED: break; case WAIT_ABANDONED: break; default: break; } CloseHandle(hConnMgrReady); filelog(L"dumpConnections...\n"); CONNMGR_CONNECTION_DETAILED_STATUS* pStatusBuffer=NULL; DWORD dwBufferSize=0; HRESULT hResult=0; //query the needed buffer size hResult = ConnMgrQueryDetailedStatus(NULL, &dwBufferSize); if(hResult==(HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))) { BYTE* bv = (BYTE*) malloc(dwBufferSize); CONNMGR_CONNECTION_DETAILED_STATUS *s= (CONNMGR_CONNECTION_DETAILED_STATUS*)&bv[0]; hResult= ConnMgrQueryDetailedStatus(s, &dwBufferSize); for (CONNMGR_CONNECTION_DETAILED_STATUS *p= s ; p ; p= p->pNext) { dump_details(p); } free(pStatusBuffer); free(bv); } }
bool ActionRedeemMotorcycle::load(Item* pItem, Slayer* pSlayer, Zone* pZone, ZoneCoord_t x, ZoneCoord_t y) const throw() { bool bFound = false; __BEGIN_TRY // 단서가 되는 아이템이 키가 아니라면 false를 리턴. if (pItem->getItemClass() != Item::ITEM_CLASS_KEY) return false; Key* pKey = dynamic_cast<Key*>(pItem); ItemID_t targetID = pKey->getTarget(); try { // 키가 맞다면 키의 타겟이 되는 아이템의 아이템 ID를 얻어낸다. Statement* pStmt = NULL; Result* pResult = NULL; // targetID가 0인 경우는.. targetID(motorcycleObject의 ItemID)가 설정이 안된 경우다. // 이 때는 임시로 targetID를 key의 ItemID와 같게 하면 된다...고 본다. // targetID가 motorcycle의 itemID로 들어가기 때문에.. // broadcasting 등에서.. Assert()에 의해서 다운되었다...고 보여진다. - -; // by sigi. 2002.12.25 x-mas T_T; if (targetID==0) { targetID = pKey->setNewMotorcycle(pSlayer); /* // (!) MotorcycleObject를 생성하고 MotorcycleItemID==Target를 받아야 한다. // 이 코드 제발 함수로 빼기를.. -_-; by sigi list<OptionType_t> optionNULL; Item* pMotorcycle = g_pItemFactoryManager->createItem(Item::ITEM_CLASS_MOTORCYCLE, 0, optionNULL); Assert(pMotorcycle != NULL); (pZone->getObjectRegistry()).registerObject(pMotorcycle); pMotorcycle->create(pSlayer->getName(), STORAGE_ZONE, pZone->getZoneID(), pSlayer->getX(), pSlayer->getY()); pKey->setTarget(pMotorcycle->getItemID()); targetID = pMotorcycle->getItemID(); // targetID를 DB에도 update시켜야 한다. BEGIN_DB { pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement(); pResult = pStmt->executeQuery( "UPDATE KeyObject SET Target=%d WHERE ItemID=%d", targetID, pKey->getItemID()); SAFE_DELETE(pStmt); } END_DB(pStmt) // 밑에서 pMotorcycle을 사용해도 되겠지만, 기존 코드 안 건드릴려고 여기서 지운다. SAFE_DELETE(pMotorcycle);*/ } else { // 한번 모터사이클이랑 키랑 연결됐는데 모터사이클을 누가 자꾸 지우나보다. // 키에 연결된 모터사이클이 실제로 디비에 있는지 체크하고 없으면 새로 만들어서 넣어준다. BEGIN_DB { pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement(); pResult = pStmt->executeQuery("SELECT ItemID FROM MotorcycleObject WHERE ItemID=%lu", targetID); if (!pResult->next() ) { Key* pKey = dynamic_cast<Key*>(pItem); Assert(pKey != NULL); targetID = pKey->setNewMotorcycle(pSlayer); } SAFE_DELETE(pStmt); } END_DB(pStmt); } // 필살 방어 코드 -_-; if (targetID==0) { filelog("errorLog.txt", "[ActionRedeemMotorcycle] itemID=%d, motorItemID=%d", (int)pItem->getItemID(), (int)targetID); return false; } // DB에 쿼리하기 전에 먼저 객체가 생성되어 있지는 않은지 체크한다. if (g_pParkingCenter->hasMotorcycleBox(targetID)) { // 자꾸 다운되어서 혹시나 하고.. // 일단 주석처리한다. by sigi. 2002.11.16 /* if (!pSlayer->hasRideMotorcycle() && !pSlayer->isFlag(Effect::EFFECT_CLASS_COMA)) { //return false; // by sigi. 2002.11.14 MotorcycleBox* pMotorcycleBox = g_pParkingCenter->getMotorcycleBox(targetID); // 있다면 소환한다. if (pMotorcycleBox!=NULL && !pMotorcycleBox->isTransport()) { Zone* pMotorZone = pMotorcycleBox->getZone(); ZoneCoord_t motorX = pMotorcycleBox->getX(); ZoneCoord_t motorY = pMotorcycleBox->getY(); Motorcycle* pMotorcycle = pMotorcycleBox->getMotorcycle(); // 같은 존에 있는 경우 // 거리가 너무 가까우면 부르지 말자~ if (pMotorZone!=pZone || pSlayer->getDistance(motorX, motorY) > 15) { // 다른 zone으로 이동중이라고 표시한다. pMotorcycleBox->setTransport(); // motorcycle을 slayer의 zone으로 옮긴다. pMotorZone->transportItem(motorX, motorY, pMotorcycle, pZone, pSlayer->getX(), pSlayer->getY()); // Use OK 대용이다. // Use하면 아이템이 사라지던가 그렇지 싶다. - -; //GCCannotUse _GCCannotUse; //_GCCannotUse.setObjectID(pPacket->getObjectID()); //pGamePlayer->sendPacket(&_GCCannotUse); // 한동안 delay를 줘야하는데.. } } return true; } */ return false; } ItemID_t itemID; ItemType_t itemType; string optionType; Durability_t durability; BEGIN_DB { StringStream sql; sql << "SELECT ItemID, ItemType, OptionType, Durability " << "FROM MotorcycleObject where ItemID = " << targetID; pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement(); pResult = pStmt->executeQuery(sql.toString()); // by sigi. 2002.10.14 // 결과물이 없다면 모터사이클이 없는 거쥐. if (pResult->getRowCount() <= 0) { bFound = false; itemID = targetID; itemType = 0; optionType = ""; durability = 300; } else { bFound = true; pResult->next(); itemID = pResult->getInt(1); itemType = pResult->getInt(2); optionType = pResult->getString(3); durability = pResult->getInt(4); } // 모터사이클 객체를 생성한다. list<OptionType_t> optionTypes; setOptionTypeFromField(optionTypes, optionType); Motorcycle* pMotorcycle = new Motorcycle(itemType, optionTypes); Assert(pMotorcycle != NULL); pMotorcycle->setItemID(itemID); pMotorcycle->setDurability(durability); // 존에다 붙이기 전에 oid를 새로 할당받는다. (pZone->getObjectRegistry()).registerObject(pMotorcycle); // 생성한 모터사이클을 존에다 갖다붙인다. TPOINT pt = pZone->addItem(pMotorcycle, x, y, false); if (pt.x == -1) { // 오토바이를 존에다 더할 수 없었다. 씨바. filelog("motorError.txt", "ActionRedeemMotorcycle::load() : 모터사이클을 존에다 더할 수 없습니다. zoneID=%d, xy=(%d, %d)", (int)pZone->getZoneID(), (int)x, (int)y); // by sigi. 2002.12.24 throw Error("ActionRedeemMotorcycle::load() : 모터사이클을 존에다 더할 수 없습니다"); } // by sigi. 2002.10.14 if (!bFound) { pStmt->executeQuery( "INSERT IGNORE INTO MotorcycleObject (ItemID, ObjectID, ItemType, OwnerID, Storage, StorageID, X, Y, OptionType, Durability) Values (%d, %d, %d, '', %d, %d, %d, %d, '', %d)", itemID, pMotorcycle->getObjectID(), itemType, STORAGE_ZONE, pZone->getZoneID(), pt.x, pt.y, durability); } // 모터사이클을 뻑킹 센터에 등록해준다. MotorcycleBox* pBox = new MotorcycleBox(pMotorcycle, pZone, pt.x, pt.y); Assert(pBox != NULL); try { g_pParkingCenter->addMotorcycleBox(pBox); } catch (DuplicatedException& de) { // by sigi. 2002.12.24 filelog("motorError.txt", "%s - itemID=%d, motorid=%d", de.toString().c_str(), itemID, pMotorcycle->getObjectID()); } bFound = true; //} SAFE_DELETE(pStmt); } END_DB(pStmt) } catch (Throwable& t) { // by sigi. 2002.12.25 filelog("motorError.txt", "%s - itemID=%d, motorItemID=%d", t.toString().c_str(), (int)pItem->getItemID(), (int)targetID); // 일단 다운은 막자. //throw; } __END_CATCH return bFound; }
//---------------------------------------------------------------------- // remove effect from target //---------------------------------------------------------------------- void EffectDecayItem::unaffect (Zone* pZone , ZoneCoord_t x , ZoneCoord_t y , Object* pTarget) throw(Error) { __BEGIN_TRY // 올바른 좌표이어야 한다. Assert(isValidZoneCoord(pZone, x, y)); // TempItem 변수를 잡는다. Item* pTempItem = NULL; // 여기서는 지정 아이템이 없을 수 있으며, 또 다른 아이템이 놓여 있을 수도 있다. // 이 경우는 오리지널 아이템과 지금 현재 바닥에 있는 아이템을 비교하여 삭제해야 한다. // 없을 경우는 무시하면 된다. Tile & tile = pZone->getTile(x, y); if (tile.hasItem()) { pTempItem = tile.getItem(); if (pTempItem != NULL) { // ObjectID가 같다는 말은 같은 아이템이란 말이다. //if (pTempItem->getObjectID() == m_ObjectID) { if (pTempItem->getObjectID() == m_ObjectID) { pZone->deleteItem(pTempItem , x, y); // 아이템이 사라졌다는 패킷을 날린다. GCDeleteObject gcDeleteObject; gcDeleteObject.setObjectID(m_ObjectID); pZone->broadcastPacket(x, y , &gcDeleteObject); if (m_bDeleteFromDB) { //ItemInfo* pItemInfo = g_pItemInfoManager->getItemInfo(pTempItem->getItemClass(), pTempItem->getItemType()); //Assert(pItemInfo!=NULL); // 유니크 아이템인 경우 개수를 줄인다. if (pTempItem->isUnique()) { // create한 아이템이 아닌 경우만 지워준다. if (pTempItem->getCreateType()!=Item::CREATE_TYPE_CREATE) UniqueItemManager::deleteItem(pTempItem->getItemClass(), pTempItem->getItemType()); filelog("uniqueItem.txt", "[EffectDecayItem] %s", pTempItem->toString().c_str()); } // ItemTraceLog 를 남긴다 /* * 존에 떨어진 아이템중 expire time인것들 모두 로그를 빼버린다. if (pTempItem != NULL && pTempItem->isTraceItem() ) { char zoneName[15]; sprintf(zoneName, "%4d%3d%3d", pZone->getZoneID(), x, y); remainTraceLog(pTempItem, zoneName, "GOD", ITEM_LOG_DELETE, DETAIL_TIMEOUT); } */ // 돈 로그 남기자 if (pTempItem->getItemClass() == Item::ITEM_CLASS_MONEY ) { Money* pMoney = dynamic_cast<Money*>(pTempItem); if (pMoney->getAmount() >= g_pVariableManager->getMoneyTraceLogLimit() ) { char zoneName[15]; sprintf(zoneName, "%4d%3d%3d", pZone->getZoneID(), x, y); remainMoneyTraceLog(zoneName, "GOD", ITEM_LOG_DELETE, DETAIL_TIMEOUT, pMoney->getAmount()); } } pTempItem->destroy(); } SAFE_DELETE(pTempItem); } } } pTarget = NULL; __END_CATCH }
void CGDisplayItemHandler::execute (CGDisplayItem* pPacket , Player* pPlayer) throw(Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ //#ifndef __TEST_SERVER__ // return; //#endif Assert(pPacket != NULL); Assert(pPlayer != NULL); GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Assert(pGamePlayer != NULL); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pGamePlayer->getCreature()); Assert(pPC != NULL); Inventory* pInventory = pPC->getInventory(); Assert(pInventory != NULL); Store* pStore = pPC->getStore(); Assert(pStore != NULL); GCSystemMessage errorMsg; GCNoticeEvent errorNotice; if (pPacket->getIndex() > MAX_ITEM_NUM ) { filelog("Store.log", "[%s:%s] (%u) 잘못된 인덱스입니다.", pGamePlayer->getID().c_str(), pPC->getName().c_str(), pPacket->getIndex()); return; } if (pPacket->getX() >= pInventory->getWidth() || pPacket->getY() >= pInventory->getHeight() ) { filelog("Store.log", "[%s:%s] (%u,%u) 인벤토리 좌표를 잘못 보내줬습니다..", pGamePlayer->getID().c_str(), pPC->getName().c_str(), pPacket->getX(), pPacket->getY()); return; } Item* pItem = pInventory->getItem(pPacket->getX(), pPacket->getY()); if (pItem == NULL || pItem->getObjectID() != pPacket->getItemObjectID() ) { filelog("Store.log", "[%s:%s] (%u, %u) : %u 아이템 좌표가 잘못되었거나 오브젝트 아이디가 잘못되었습니다.", pGamePlayer->getID().c_str(), pPC->getName().c_str(), pPacket->getX(), pPacket->getY(), pPacket->getItemObjectID()); return; } if (pPC->getZone()->getTradeManager()->getTradeInfo(pPC->getName() ) != NULL ) { filelog("Store.log", "[%s:%s] : 거래중에는 물건을 올려놓을 수 없습니다.", pGamePlayer->getID().c_str(), pPC->getName().c_str()); return; } if (pStore->hasItem(pItem ) ) { filelog("Store.log", "[%s:%s] (%u, %u) 이미 아이템이 상점에 있습니다.", pGamePlayer->getID().c_str(), pPC->getName().c_str(), pItem->getObjectID(), pPacket->getIndex()); // errorMsg.setMessage("이미 진열된 아이템입니다."); errorNotice.setCode(NOTICE_EVENT_ALREADY_DISPLAYED); pGamePlayer->sendPacket(&errorNotice); return; } if (pItem->isTimeLimitItem() || !canSell(pItem ) || !canTrade(pItem ) || !canTradeInventoryItem(pItem ) ) { filelog("Store.log", "[%s:%s] (%s) 팔 수 없는 아이템입니다.", pGamePlayer->getID().c_str(), pPC->getName().c_str(), pItem->toString().c_str()); // errorMsg.setMessage("판매할 수 없는 아이템입니다."); errorNotice.setCode(NOTICE_EVENT_CANNOT_SELL); pGamePlayer->sendPacket(&errorNotice); return; } BYTE result = pStore->setStoreItem(pPacket->getIndex(), pItem, pPacket->getPrice()); if ( result != 0 ) { filelog("Store.log", "[%s:%s] (%u) 아이템을 놓을 수 없습니다.", pGamePlayer->getID().c_str(), pPC->getName().c_str(), result); return; } GCMyStoreInfo gcInfo; gcInfo.setStoreInfo(&(pStore->getStoreInfo())); pGamePlayer->sendPacket(&gcInfo); if (pStore->isOpen() ) { GCAddStoreItem gcAdd; gcAdd.setOwnerObjectID(pPC->getObjectID()); gcAdd.setIndex(pPacket->getIndex()); pStore->getStoreItem(pPacket->getIndex() ).makeStoreItemInfo(gcAdd.getItem()); pPC->getZone()->broadcastPacket(pPC->getX(), pPC->getY(), &gcAdd, pPC); } #endif // __GAME_SERVER__ __END_DEBUG_EX __END_CATCH }
void CLLoginHandler::execute (CLLogin* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __LOGIN_SERVER__ Assert(pPacket != NULL); Assert(pPlayer != NULL); //cout << pPacket->toString().c_str() << endl; LoginPlayer* pLoginPlayer = dynamic_cast<LoginPlayer*>(pPlayer); Statement* pStmt = NULL; // 좌우 공백 제거. by sigi. 2002.12.6 pPacket->setID(trim(pPacket->getID())); string connectIP = pLoginPlayer->getSocket()->getHost(); string connectMAC = pPacket->getMacAddress(); string ID = pPacket->getID(); // MAC address setting pLoginPlayer->setMacAddress(pPacket->getRareMacAddress()); bool bFreePass = false; //by sigi. 2002.10.23j // web login bool bWebLogin = pPacket->isWebLogin(); // static bool bWebLogin = g_pConfig->getPropertyInt("WebLogin") != 0; // set web login player if (bWebLogin ) pLoginPlayer->setWebLogin(); // cout << pPacket->toString() << endl; if (isBlockIP(connectIP) ) { LCLoginError lcLoginError; lcLoginError.setErrorID(IP_DENYED); pLoginPlayer->sendPacket(&lcLoginError); filelog("loginfail.txt", "Error Code: IP_DENYED, 1, PlayerID : %s", pPacket->getID().c_str()); return; } // 사내테스트 버전에서는 '#sigi' <-- 이런 식으로 계정이 들어온다. if (ID[0]==SYMBOL_TEST_CLIENT) { ID = ID.c_str()+1; pPacket->setID(ID); // 웹 로그인 체크 if (bWebLogin ) { //cout << "WebLogin" << endl; if (!checkWebLogin(pPacket, pPlayer ) ) { return; } //else //cout << "Web Login OK" << endl; } else { //cout << "not WebLogin" << endl; // 넷마블에서 접속하는 경우 // by sigi. 2002.10.23 if (!checkNetMarbleClient(pPacket, pPlayer )) { return; } } bFreePass = pLoginPlayer->isFreePass(); if (!bWebLogin && bFreePass) { // 웹로그인이 아닌 FreePass 는 넷마블 사용자로 ID 앞에 예약문자가 하나더 있다. ID = ID.c_str()+1; pPacket->setID(ID); } // cout << "테스트 클라이언트" << endl; BEGIN_DB { // 증거를 남긴다. pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement(); pStmt->executeQuery( "INSERT INTO TestClientUser (PlayerID, IP, LoginDate) VALUES ('%s', '%s', now())", ID.c_str(), connectIP.c_str()); SAFE_DELETE(pStmt); } END_DB(pStmt) }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionTradeGiftBox::execute(Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2); Assert(pPC != NULL); Player* pPlayer = pPC->getPlayer(); Assert(pPlayer != NULL); Inventory* pInventory = pPC->getInventory(); Assert(pInventory != NULL); Zone* pZone = pPC->getZone(); Assert(pZone != NULL); FlagSet* pFlagSet = pPC->getFlagSet(); Item::ItemClass ItemClass; ItemType_t ItemType; OptionType_t OptionType; Item* pItem; Item* pGiftBoxItem; // 이미 선물을 교환해 갔다면 if (pFlagSet->isOn(FLAGSET_TRADE_GIFT_BOX_2002_12 ) ) { GCNPCResponse response; response.setCode(NPC_RESPONSE_TRADE_GIFT_BOX_ALREADY_TRADE); pPlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } // 빨간 선물 상자가 있는지 확인한다. CoordInven_t X,Y; pGiftBoxItem = pInventory->findItem(Item::ITEM_CLASS_EVENT_GIFT_BOX, 1, X, Y); if (pGiftBoxItem == NULL ) { GCNPCResponse response; response.setCode(NPC_RESPONSE_TRADE_GIFT_BOX_NO_ITEM); pPlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } LuaSelectItem* pLuaSelectItem = NULL; string luaFileName; if (pPC->isSlayer() ) { // 루아에 슬레이어 능력치의 합을 set한다. Slayer* pSlayer = dynamic_cast<Slayer*>(pPC); Assert(pSlayer != NULL); Attr_t sum = pSlayer->getSTR(ATTR_BASIC ) + pSlayer->getDEX(ATTR_BASIC ) + pSlayer->getINT(ATTR_BASIC); m_pLuaSlayerItem->setSum(sum); pLuaSelectItem = m_pLuaSlayerItem; luaFileName = m_SlayerFilename; } else if (pPC->isVampire() ) { // 루아에 뱀파이어의 레벨을 set한다. Vampire* pVampire = dynamic_cast<Vampire*>(pPC); Assert(pVampire != NULL); int level = pVampire->getLevel(); m_pLuaVampireItem->setLevel(level); pLuaSelectItem = m_pLuaVampireItem; luaFileName = m_VampireFilename; } //-------------------------------------------------------- // 속도 체크를 위해서 1000번 돌려보는 코드 // 결과는.. 0.07초 정도 나왔다. 감덩~ -_-; /* Timeval beforeTime; getCurrentTime(beforeTime); for (int i=0; i<1000; i++) { // 루아의 계산 결과를 받아 아이템을 생성한다. pLuaSelectItem->prepare(); int result = pLuaSelectItem->executeFile(luaFileName); LuaState::logError(result); pLuaSelectItem->clear(); } Timeval afterTime; getCurrentTime(afterTime); cout << "luaExecute time before : " << beforeTime.tv_sec << "." << beforeTime.tv_usec << endl; cout << "luaExecute time after : " << afterTime.tv_sec << "." << afterTime.tv_usec << endl; */ //-------------------------------------------------------- // 루아의 계산 결과를 받아 아이템을 생성한다. pLuaSelectItem->prepare(); int result = pLuaSelectItem->executeFile(luaFileName); LuaState::logError(result); ItemClass = pLuaSelectItem->getItemClass(); ItemType = pLuaSelectItem->getItemType(); OptionType = pLuaSelectItem->getOptionType(); pLuaSelectItem->clear(); if(ItemClass >= Item::ITEM_CLASS_MAX ) //|| ItemType >= ITEM_TYPE_MAX || ItemType < 0 // || OptionType == 0) { filelog("XMasEventError.txt", "[ ItemInfo Error ] : ItemClass = %d , ItemType = %d , OptionType = %d", ItemClass, ItemType, OptionType); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); return; } // 클라이언트에 선물상자를 지우도록 한다. GCDeleteInventoryItem gcDeleteInventoryItem; gcDeleteInventoryItem.setObjectID(pGiftBoxItem->getObjectID()); pPlayer->sendPacket(&gcDeleteInventoryItem); // 선물상자를 지운다. pInventory->deleteItem(X, Y); // ItemTraceLog 를 남긴다 if (pGiftBoxItem != NULL && pGiftBoxItem->isTraceItem() ) { remainTraceLog(pGiftBoxItem, pCreature2->getName(), pCreature1->getName(), ITEM_LOG_DELETE, DETAIL_EVENTNPC); } pGiftBoxItem->destroy(); SAFE_DELETE(pGiftBoxItem); // 선물(Item)을 만든다. list<OptionType_t> optionTypeList; if (OptionType != 0 ) optionTypeList.push_back(OptionType); pItem = g_pItemFactoryManager->createItem(ItemClass, ItemType, optionTypeList); Assert(pItem != NULL); // 선물을 인벤토리에 추가한다. pZone->getObjectRegistry().registerObject(pItem); pInventory->addItem(X, Y, pItem); pItem->create(pPC->getName(), STORAGE_INVENTORY, 0, X, Y); // ItemTraceLog 를 남긴다 if (pItem != NULL && pItem->isTraceItem() ) { remainTraceLog(pItem, pCreature1->getName(), pCreature2->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC); } // 클라이언트에 선물이 추가되었음을 알린다. GCCreateItem gcCreateItem; makeGCCreateItem(&gcCreateItem, pItem, X, Y); pPlayer->sendPacket(&gcCreateItem); // Flag을 켠다. pFlagSet->turnOn(FLAGSET_TRADE_GIFT_BOX_2002_12); // Flag을 저장한다. pFlagSet->save(pPC->getName()); // 아이템 교환이 이루어 졌다고 클라이언트에 알린다. GCNPCResponse response; response.setCode(NPC_RESPONSE_TRADE_GIFT_BOX_OK); pPlayer->sendPacket(&response); GCNPCResponse quit; quit.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&quit); __END_CATCH }
void CGShopRequestSellHandler::executeOpSwapAdvancementItem(CGShopRequestSell* pPacket, Player* pPlayer) throw(ProtocolException, Error) { __BEGIN_TRY #ifdef __GAME_SERVER__ ObjectID_t NPCID = pPacket->getObjectID(); ObjectID_t ITEMOID = pPacket->getItemObjectID(); GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Creature* pCreature = pGamePlayer->getCreature(); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature); if (!pPC->isAdvanced() ) { return sendFailPacket(pPacket, pPlayer); } Zone* pZone = pPC->getZone(); if (pZone == NULL) return sendFailPacket(pPacket, pPlayer); Creature* pNPCBase = pZone->getCreature(NPCID); if (pNPCBase == NULL || !pNPCBase->isNPC()) return sendFailPacket(pPacket, pPlayer); NPC* pNPC = dynamic_cast<NPC*>(pNPCBase); Inventory* pInventory = pPC->getInventory(); Item* pItem = pInventory->getItemWithObjectID(ITEMOID); if (pItem == NULL || pItem->isTimeLimitItem() ) { return sendFailPacket(pPacket, pPlayer); } Item::ItemClass iClass = Item::ITEM_CLASS_MAX; ItemType_t iType = 0; Grade_t iGrade = 0; FlagSetType fType = FLAGSET_MAX; ItemInfo* pItemInfo = g_pItemInfoManager->getItemInfo(pItem->getItemClass(), pItem->getItemType()); Assert(pItemInfo!=NULL); switch (pItem->getItemClass() ) { case Item::ITEM_CLASS_SWORD: case Item::ITEM_CLASS_BLADE: case Item::ITEM_CLASS_AR: case Item::ITEM_CLASS_SR: case Item::ITEM_CLASS_SG: case Item::ITEM_CLASS_SMG: { switch (pItem->getItemType() ) { case 9: { iClass = pItem->getItemClass(); iType = 14; iGrade = 2; break; } case 11: { iClass = pItem->getItemClass(); iType = 14; iGrade = 4; break; } case 12: { iClass = pItem->getItemClass(); iType = 14; iGrade = 6; break; } case 13: { iClass = pItem->getItemClass(); iType = 14; iGrade = 8; break; } default: break; } if (iClass == Item::ITEM_CLASS_SG ) iClass = Item::ITEM_CLASS_SR; if (iClass == Item::ITEM_CLASS_SMG ) iClass = Item::ITEM_CLASS_AR; break; } case Item::ITEM_CLASS_CROSS: case Item::ITEM_CLASS_MACE: { switch (pItem->getItemType() ) { case 7: { iClass = pItem->getItemClass(); iType = 12; iGrade = 2; break; } case 9: { iClass = pItem->getItemClass(); iType = 12; iGrade = 4; break; } case 10: { iClass = pItem->getItemClass(); iType = 12; iGrade = 6; break; } case 11: { iClass = pItem->getItemClass(); iType = 12; iGrade = 8; break; } default: break; } break; } case Item::ITEM_CLASS_COAT: case Item::ITEM_CLASS_TROUSER: { switch (pItem->getItemType() ) { case 14: case 15: { iClass = pItem->getItemClass(); iType = 24 + (pItem->getItemType()%2); iGrade = 2; break; } case 18: case 19: case 20: case 21: case 22: case 23: { iClass = pItem->getItemClass(); iType = 24 + (pItem->getItemType()%2); iGrade = 4 + (((pItem->getItemType()-18)/2)*2); break; } default: break; } break; } case Item::ITEM_CLASS_VAMPIRE_WEAPON: { switch (pItem->getItemType() ) { case 14: { iClass = pItem->getItemClass(); iType = 19; iGrade = 2; break; } case 16: { iClass = pItem->getItemClass(); iType = 19; iGrade = 4; break; } case 17: { iClass = pItem->getItemClass(); iType = 19; iGrade = 6; break; } case 18: { iClass = pItem->getItemClass(); iType = 19; iGrade = 8; break; } default: break; } break; } case Item::ITEM_CLASS_VAMPIRE_COAT: { switch (pItem->getItemType() ) { case 10: case 11: { iClass = pItem->getItemClass(); iType = 20 + (pItem->getItemType()%2); iGrade = 2; break; } case 14: case 15: case 16: case 17: case 18: case 19: { iClass = pItem->getItemClass(); iType = 20 + (pItem->getItemType()%2); iGrade = 4 + (((pItem->getItemType()-14)/2)*2); break; } default: break; } break; } case Item::ITEM_CLASS_OUSTERS_CHAKRAM: { switch (pItem->getItemType() ) { case 9: { iClass = pItem->getItemClass(); iType = 14; iGrade = 2; break; } case 10: { iClass = pItem->getItemClass(); iType = 14; iGrade = 4; break; } case 11: { iClass = pItem->getItemClass(); iType = 14; iGrade = 6; break; } case 13: { iClass = pItem->getItemClass(); iType = 14; iGrade = 8; break; } default: break; } break; } case Item::ITEM_CLASS_OUSTERS_WRISTLET: { switch (pItem->getItemType() ) { case 9: case 30: case 31: case 39: { iClass = pItem->getItemClass(); iType = 42; iGrade = pItemInfo->getItemLevel() * 2 - 16; break; } case 19: case 32: case 33: case 40: { iClass = pItem->getItemClass(); iType = 43; iGrade = pItemInfo->getItemLevel() * 2 - 16; break; } case 29: case 34: case 35: case 41: { iClass = pItem->getItemClass(); iType = 44; iGrade = pItemInfo->getItemLevel() * 2 - 16; break; } default: break; } break; } case Item::ITEM_CLASS_OUSTERS_COAT: case Item::ITEM_CLASS_OUSTERS_BOOTS: { switch (pItem->getItemType() ) { case 7: { iClass = pItem->getItemClass(); iType = 12; iGrade = 2; break; } case 8: { iClass = pItem->getItemClass(); iType = 12; iGrade = 4; break; } case 9: { iClass = pItem->getItemClass(); iType = 12; iGrade = 6; break; } case 11: { iClass = pItem->getItemClass(); iType = 12; iGrade = 8; break; } default: break; } break; } default: break; } switch (iClass ) { case Item::ITEM_CLASS_SWORD: case Item::ITEM_CLASS_BLADE: case Item::ITEM_CLASS_AR: case Item::ITEM_CLASS_SR: case Item::ITEM_CLASS_CROSS: case Item::ITEM_CLASS_MACE: case Item::ITEM_CLASS_VAMPIRE_WEAPON: case Item::ITEM_CLASS_OUSTERS_CHAKRAM: case Item::ITEM_CLASS_OUSTERS_WRISTLET: fType = FLAGSET_SWAP_WEAPON; break; case Item::ITEM_CLASS_COAT: case Item::ITEM_CLASS_VAMPIRE_COAT: case Item::ITEM_CLASS_OUSTERS_COAT: fType = FLAGSET_SWAP_COAT; break; case Item::ITEM_CLASS_TROUSER: case Item::ITEM_CLASS_OUSTERS_BOOTS: fType = FLAGSET_SWAP_TROUSER; break; default: break; } if (iClass == Item::ITEM_CLASS_MAX || fType == FLAGSET_MAX ) { sendFailPacket(pPacket, pPlayer); return; } FlagSet* pFlagSet = pPC->getFlagSet(); if (pFlagSet->isOn(fType) ) { sendFailPacket(pPacket, pPlayer); return; } Item* pNewItem = g_pItemFactoryManager->createItem(iClass, iType, pItem->getOptionTypeList()); if (pNewItem == NULL ) { sendFailPacket(pPacket, pPlayer); return; } pNewItem->setGrade(iGrade); _TPOINT tp; if (!pInventory->getEmptySlot(pNewItem, tp) ) { SAFE_DELETE(pNewItem); sendFailPacket(pPacket, pPlayer); return; } filelog("ItemSwap.log", "[%s:%s] %s <-> %s", pGamePlayer->getID().c_str(), pPC->getName().c_str(), pItem->toString().c_str(), pNewItem->toString().c_str()); pNewItem->setTraceItem(bTraceLog(pNewItem )); pInventory->deleteItem(ITEMOID); pItem->whenPCLost(pPC); if (!pItem->destroy()) { filelog("shopDBBug.txt", "NoSuchItemInDB-destroy: %s", pItem->toString().c_str()); throw DisconnectException("아이템 지울려는데 DB에 없다."); } pZone->registerObject(pNewItem); GCShopSellOK okpkt; okpkt.setObjectID(NPCID); okpkt.setShopVersion(-1); okpkt.setItemObjectID(ITEMOID); okpkt.setPrice(0); pGamePlayer->sendPacket(&okpkt); // 삭제할 아이템의 ItemTrace Log 를 남겨야 한다면 남긴다 if (pItem != NULL && pItem->isTraceItem() ) { remainTraceLog(pItem, pCreature->getName() , pNPC->getName(), ITEM_LOG_DELETE, DETAIL_SHOPSELL); } // 인벤토리에 추가 Assert(pInventory->addItem(pNewItem, tp )); // DB 에 생성 pNewItem->create(pPC->getName(), STORAGE_INVENTORY, 0, tp.x, tp.y); // 교환해줄 아이템의 ItemTrace Log 를 남겨야 한다면 남긴다 if (pNewItem->isTraceItem() ) { remainTraceLog(pNewItem, pNPC->getName() , pCreature->getName(), ITEM_LOG_CREATE, DETAIL_SHOPBUY); } pFlagSet->turnOn(fType); pFlagSet->save(pPC->getName()); GCCreateItem gcCI; makeGCCreateItem(&gcCI, pNewItem, tp.x, tp.y); pGamePlayer->sendPacket(&gcCI); #endif __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // // 모터 사이클을 처리한다. // ////////////////////////////////////////////////////////////////////////////// void CGShopRequestSellHandler::executeMotorcycle (CGShopRequestSell* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ // 패킷 정보를 뽑아낸다. ObjectID_t NPCID = pPacket->getObjectID(); ObjectID_t ITEMOID = pPacket->getItemObjectID(); GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Creature* pCreature = pGamePlayer->getCreature(); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature); Zone* pZone = pPC->getZone(); if (pZone == NULL) return sendFailPacket(pPacket, pPlayer); Creature* pNPCBase = NULL; /* try { pNPCBase = pZone->getCreature(NPCID); } catch (NoSuchElementException & nsee) { pNPCBase = NULL; } */ // NoSuch제거. by sigi. 2002.5.2 pNPCBase = pZone->getCreature(NPCID); if (pNPCBase == NULL || !pNPCBase->isNPC()) return sendFailPacket(pPacket, pPlayer); NPC* pNPC = dynamic_cast<NPC*>(pNPCBase); int CenterX = pNPC->getX(); int CenterY = pNPC->getY(); // 플레이어가 팔려고 하는 아이템을 가지고 있는지 검사 Inventory* pInventory = pPC->getInventory(); Gold_t playerMoney = pPC->getGold(); Item* pItem = pInventory->getItemWithObjectID(ITEMOID); if (pItem == NULL) return sendFailPacket(pPacket, pPlayer); // 주위 일정 범위를 검색해서, 모터 사이클이 있는지 확인한다. try { for (int zx=CenterX-5; zx<=CenterX+5; zx++) { for (int zy=CenterY-5; zy<=CenterY+5; zy++) { // 바운드를 넘어가지 않는가를 체크 if (!isValidZoneCoord(pZone, zx, zy)) continue; Tile & tile = pZone->getTile(zx, zy); if (tile.hasItem()) { Item* pItemOnTile = tile.getItem(); if (pItemOnTile == NULL) continue; // 만일 아이템이 타일 위에 있을 경우, 모터 사이클인지 확인한다. if (pItemOnTile->getItemClass() == Item::ITEM_CLASS_MOTORCYCLE) { DWORD targetID = dynamic_cast<Key*>(pItem)->getTarget(); ItemID_t motorcycleID = pItemOnTile->getItemID(); if (targetID == motorcycleID) { // 모터사이클을 DB에서 삭제한다. pItemOnTile->destroy(); // 플레이어의 인벤토리에서 열쇠를 제거한다. pInventory->deleteItem(ITEMOID); pItem->destroy(); SAFE_DELETE(pItem); // 열쇠 값이 아니라, 오토바이 값을 줘야 한다. Price_t itemPrice = g_pPriceManager->getPrice(pItemOnTile, pNPC->getMarketCondBuy(), SHOP_RACK_NORMAL, pPC); // 플레이어의 돈을 늘린다. //pPC->setGoldEx(playerMoney+itemPrice); // by sigi. 2002.9.4 pPC->increaseGoldEx(itemPrice); // 물건을 판 플레이어에게 GCShopSellOK를...보낸다. GCShopSellOK okpkt; okpkt.setObjectID(NPCID); if (!pItemOnTile->getOptionTypeList().empty()) okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_SPECIAL)); else okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_NORMAL)); okpkt.setItemObjectID(ITEMOID); okpkt.setPrice(playerMoney+itemPrice); pPlayer->sendPacket(&okpkt); // 뻑킹 센터에서 박스를 삭제해 준다. if (g_pParkingCenter->hasMotorcycleBox(motorcycleID)) g_pParkingCenter->deleteMotorcycleBox(motorcycleID); // NPC에게 자리가 충분하다면 플레이어가 판 아이템을 보관한다. // 단 스페셜 아이템만을 보관한다. 노말 아이템은 그냥 버림. //if (pItemOnTile->getOptionType() != 0) //{ // index = pNPC->getFirstEmptySlot(SHOP_RACK_SPECIAL); // if (index < SHOP_RACK_INDEX_MAX) // { // pNPC->insertShopItem(SHOP_RACK_SPECIAL, index, pItemOnTile); // // 스페셜 아이템을 NPC가 진열장에 추가했으므로, 상점 버전이 올라간다. // pNPC->increaseShopVersion(SHOP_RACK_SPECIAL); // } //} //else //{ // SAFE_DELETE(pItemOnTile); //} // 모터 사이클을 찾았으므로, 할 일이 끝났다. return; } } } } // end of for (ZoneCoord_t zy=CenterY-5; zy<=CenterY+5; zy++) } // end of for (ZoneCoord_t zx=CenterX-5; zx<=CenterX+5; zx++) } catch (Throwable & t) { filelog("shopbug_packet.log", "%s", t.toString().c_str()); } // FOR 루프를 다 돌고, 이까지 왔다는 것은 근처에 오토바이가 없다는 말이당... // 그러므로 모터 사이클 팔기가 실패했다는 것을 알린다. GCShopSellFail failpkt; failpkt.setObjectID(NPCID); pPlayer->sendPacket(&failpkt); #endif __END_DEBUG_EX __END_CATCH }
////////////////////////////////////////////////////////////////////////////// // // 일반 아이템을 처리한다. // ////////////////////////////////////////////////////////////////////////////// void CGShopRequestSellHandler::executeNormal (CGShopRequestSell* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ ObjectID_t NPCID = pPacket->getObjectID(); ObjectID_t ITEMOID = pPacket->getItemObjectID(); GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Creature* pCreature = pGamePlayer->getCreature(); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature); BYTE index = 0; bool bSpecialItem = false; Zone* pZone = pPC->getZone(); if (pZone == NULL) return sendFailPacket(pPacket, pPlayer); Creature* pNPCBase = NULL; /* try { pNPCBase = pZone->getCreature(NPCID); } catch (NoSuchElementException & nsee) { pNPCBase = NULL; } */ // NoSuch제거. by sigi. 2002.5.2 pNPCBase = pZone->getCreature(NPCID); if (pNPCBase == NULL || !pNPCBase->isNPC()) return sendFailPacket(pPacket, pPlayer); NPC* pNPC = dynamic_cast<NPC*>(pNPCBase); // 플레이어가 팔려고 하는 아이템을 가지고 있는지 검사 Inventory* pInventory = pPC->getInventory(); //Gold_t playerMoney = pPC->getGold(); Item* pItem = pInventory->getItemWithObjectID(ITEMOID); ItemNum_t itemNumber = pItem->getNum(); Price_t itemPrice = g_pPriceManager->getPrice(pItem, pNPC->getMarketCondBuy(), SHOP_RACK_NORMAL, pPC) * itemNumber; // 플레이어의 인벤토리에 아이템을 제거한다. pInventory->deleteItem(ITEMOID); pItem->whenPCLost(pPC); if (!pItem->destroy()) { filelog("shopDBBug.txt", "NoSuchItemInDB-destroy: %s", pItem->toString().c_str()); throw DisconnectException("아이템 지울려는데 DB에 없다."); } // 만약 벨트라면 안에 있는 포션을 삭제해준다. // DB에서 지우는 것은 Belt::destroy()를 부르는 것만으로 포션까지 삭제된다. if (pItem->getItemClass() == Item::ITEM_CLASS_BELT) { Inventory* pBeltInventory = dynamic_cast<Belt*>(pItem)->getInventory(); for (int y=0; y<pBeltInventory->getHeight(); y++) { for (int x=0; x<pBeltInventory->getWidth(); x++) { Item* pBeltItem = pBeltInventory->getItem(x, y); if (pBeltItem != NULL) { pBeltInventory->deleteItem(x, y); SAFE_DELETE(pBeltItem); } } } } // Skull 일 경우 Variable Manager 에서 머리값 배수 값으로 가격을 새로 계산한다 if (pItem->getItemClass() == Item::ITEM_CLASS_SKULL) itemPrice = itemPrice * (g_pVariableManager->getHeadPriceBonus() / 100); // ItemTrace Log 를 남겨야 한다면 남긴다 if (pItem != NULL && pItem->isTraceItem() ) remainTraceLog(pItem, pCreature->getName() , pNPC->getName(), ITEM_LOG_DELETE, DETAIL_SHOPSELL); // 플레이어에게 물건값을 지불한다. // pPC->setGoldEx(playerMoney+itemPrice); // by sigi. 2002.9.4 pPC->increaseGoldEx(itemPrice); // 플레이어가 물건 팔 때 처리할 것들을 처리한다. pPC->sellItem(pItem); if (pItem->getItemClass() == Item::ITEM_CLASS_MOON_CARD && pItem->getItemType() == 4) addOlympicStat(pPC, 4, (uint)(itemNumber)); bool bClearDefaultOptionTypes = false; if (pItem->getItemClass() == Item::ITEM_CLASS_EVENT_ITEM && pItem->getItemType() >= 32 && pItem->getItemType() <= 36) bClearDefaultOptionTypes = true; // NPC에게 자리가 충분하다면 플레이어가 판 아이템을 보관한다. // 운영자 명령어로 만든 아이템은 바로 없앤다. // 단 스페셜 아이템만을 보관한다. 노말 아이템은 그냥 버림. // 퀘스트 아이템은 보관하지 않고 버린다. if (pNPC->getShopType()==SHOPTYPE_NORMAL && pItem->getCreateType()!=Item::CREATE_TYPE_CREATE && !pItem->getOptionTypeList().empty() && !pItem->isTimeLimitItem()) { bSpecialItem = true; index = pNPC->getFirstEmptySlot(SHOP_RACK_SPECIAL); if (index < SHOP_RACK_INDEX_MAX) { // 아이템을 추가한다. pNPC->insertShopItem(SHOP_RACK_SPECIAL, index, pItem); // 스페셜 아이템을 NPC가 진열장에 추가했으므로, 상점 버전이 올라간다. pNPC->increaseShopVersion(SHOP_RACK_SPECIAL); //////////////////////////////////////////////////////////////////////////// // 근처의 플레이어들에게는 GCShopBought를... //////////////////////////////////////////////////////////////////////////// int CenterX = pNPC->getX(); int CenterY = pNPC->getY(); Creature* pNearCreature = NULL; Player* pNearPlayer = NULL; GCShopBought boughtpkt; boughtpkt.setObjectID(NPCID); if (!pItem->getOptionTypeList().empty()) { boughtpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_SPECIAL)); boughtpkt.setShopType(SHOP_RACK_SPECIAL); } else { boughtpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_NORMAL)); boughtpkt.setShopType(SHOP_RACK_NORMAL); } boughtpkt.setShopIndex(index); boughtpkt.setItemObjectID(ITEMOID); boughtpkt.setItemClass(pItem->getItemClass()); boughtpkt.setItemType(pItem->getItemType()); boughtpkt.setOptionType(pItem->getOptionTypeList()); boughtpkt.setDurability(pItem->getDurability()); boughtpkt.setSilver(pItem->getSilver()); boughtpkt.setGrade(pItem->getGrade()); boughtpkt.setEnchantLevel(pItem->getEnchantLevel()); //pZone->broadcastPacket(pNPC->getX(), pNPC->getY(), &boughtpkt, pPC); try { for (int zx=CenterX-5; zx<=CenterX+5; zx++) { for (int zy=CenterY-5; zy<=CenterY+5; zy++) { // 바운드를 넘어가지 않는가를 체크 if (!isValidZoneCoord(pZone, zx, zy)) continue; Tile & tile = pZone->getTile(zx, zy); // 걸어다니는 크리쳐를 검색 if (tile.hasCreature(Creature::MOVE_MODE_WALKING)) { pNearCreature = tile.getCreature(Creature::MOVE_MODE_WALKING); if (pNearCreature == NULL) continue; // 방금 물건을 판 플레이어라면 생략 if (pNearCreature->getObjectID() == pPC->getObjectID()) continue; // 만약 플레이어라면 패킷을 보내준다. if (pNearCreature->isPC()) { pNearPlayer = pNearCreature->getPlayer(); if (pNearPlayer == NULL) continue; pNearPlayer->sendPacket(&boughtpkt); } } // 날아다니는 크리쳐를 검색 if (tile.hasCreature(Creature::MOVE_MODE_FLYING)) { pNearCreature = tile.getCreature(Creature::MOVE_MODE_FLYING); if (pNearCreature == NULL) continue; // 방금 물건을 판 플레이어라면 생략 if (pNearCreature->getObjectID() == pPC->getObjectID()) continue; // 만약 플레이어라면 패킷을 보내준다. if (pNearCreature->isPC()) { pNearPlayer = pNearCreature->getPlayer(); if (pNearPlayer == NULL) continue; pNearPlayer->sendPacket(&boughtpkt); } } } // end of for (ZoneCoord_t zy=CenterY-5; zy<=CenterY+5; zy++) } // end of for (ZoneCoord_t zx=CenterX-5; zx<=CenterX+5; zx++) } catch (Throwable & t) { filelog("shopbug_packet.log", "%s", t.toString().c_str()); } } // if (index < SHOP_RACK_INDEX_MAX) else { SAFE_DELETE(pItem); } } // if (pItem->getOptionType() != 0) else { bSpecialItem = false; SAFE_DELETE(pItem); } // 물건을 산 플레이어에게 GCShopSellOK를...보낸다. GCShopSellOK okpkt; okpkt.setObjectID(NPCID); if (bSpecialItem) okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_SPECIAL)); else okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_NORMAL)); okpkt.setItemObjectID(ITEMOID); //okpkt.setPrice(playerMoney+itemPrice); // playerMoney + itemPrice 가 MAX_MONEY를 넘어갈 수 있다. // 2003.1.8 by bezz okpkt.setPrice(pPC->getGold()); pPlayer->sendPacket(&okpkt); if (bClearDefaultOptionTypes ) { pPC->clearDefaultOptionTypes(); pPC->initAllStatAndSend(); if (pPC->isSlayer() ) { Slayer* pSlayer = dynamic_cast<Slayer*>(pPC); Assert(pSlayer != NULL); pSlayer->sendRealWearingInfo(); } else if (pPC->isVampire() ) { Vampire* pVampire = dynamic_cast<Vampire*>(pPC); Assert(pVampire != NULL); pVampire->sendRealWearingInfo(); } else if (pPC->isOusters() ) { Ousters* pOusters = dynamic_cast<Ousters*>(pPC); Assert(pOusters != NULL); pOusters->sendRealWearingInfo(); } } #endif __END_DEBUG_EX __END_CATCH }