//! deletes one item from inventory int Script::deleteItem(lua_State* L){ short tx = (short)luaL_checknumber(L, 1); short ty = (short)luaL_checknumber(L, 2); string name = string(luaL_checkstring(L, 3)); Creature* creat = dynamic_cast<Creature*>(wrld.getObject(Vector2D(tx,ty))); Inventory* inv = creat->getInventory(); bool done = inv->deleteItem(name); lua_pushboolean(L, done); return 1; }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// 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::executeOpAllSkull (CGShopRequestSell* pPacket , Player* pPlayer) throw(ProtocolException , Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ ObjectID_t NPCID = pPacket->getObjectID(); 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); Inventory* pInventory = pPC->getInventory(); // by sigi. 2002.9.4 //Gold_t playerMoney = pPC->getGold(); Price_t itemPrice = 0; Item* pItem = NULL; for (uint y=0; y<pInventory->getHeight(); y++) { for (uint x=0; x<pInventory->getWidth(); x++) { pItem = pInventory->getItem(x, y); // 아이템이 존재하고, 해골이라면... if (pItem != NULL && pItem->getItemClass() == Item::ITEM_CLASS_SKULL) { // 아이템 가격을 계산해서 플레이어의 돈에다 더한다. //itemPrice = g_pPriceManager->getPrice(pItem, pNPC->getMarketCondBuy(), SHOP_RACK_NORMAL, pPC) * pItem->getNum(); //playerMoney += itemPrice; // by sigi. 2002.9.4 itemPrice += g_pPriceManager->getPrice(pItem, pNPC->getMarketCondBuy(), SHOP_RACK_NORMAL, pPC) * pItem->getNum(); // 인벤토리 및 DB에서 아이템을 삭제한다. pInventory->deleteItem(x, y); pItem->destroy(); SAFE_DELETE(pItem); } } } itemPrice = itemPrice * (g_pVariableManager->getHeadPriceBonus() / 100); // 플레이어에게 물건값을 지불한다. //pPC->setGoldEx(playerMoney); // by sigi. 2002.9.4 pPC->increaseGoldEx(itemPrice); // 물건을 산 플레이어에게 GCShopSellOK를...보낸다. GCShopSellOK okpkt; okpkt.setObjectID(NPCID); okpkt.setShopVersion(pNPC->getShopVersion(SHOP_RACK_NORMAL)); okpkt.setItemObjectID(0); okpkt.setPrice(pPC->getGold()); pPlayer->sendPacket(&okpkt); #endif __END_DEBUG_EX __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 }
////////////////////////////////////////////////////////////////////////////// // 뱀파이어 인벤토리 핸들러 ////////////////////////////////////////////////////////////////////////////// void BloodyTunnel::execute(Vampire* pVampire, ObjectID_t InvenObjectID, ObjectID_t InventoryItemObjectID, CoordInven_t X, CoordInven_t Y, CoordInven_t TargetX, CoordInven_t TargetY, VampireSkillSlot* pSkillSlot) throw(Error) { __BEGIN_TRY //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " Begin" << endl; Assert(pVampire != NULL); Assert(pSkillSlot != NULL); try { Player* pPlayer = pVampire->getPlayer(); Zone* pZone = pVampire->getZone(); Inventory* pInventory = pVampire->getInventory(); Assert(pPlayer != NULL); Assert(pZone != NULL); Assert(pInventory!= NULL); // 전쟁 존이라면 BloodyTunnel를 사용할 수 없다. // 일단은 ZoneID로 가는데.. ZoneInfo에 넣도록 해야한다. ///* //if (pZone->getZoneID()==1122 || pZone->getZoneID()==1123) // 이벤트 경기장/OX 막기. by sigi. 2002.8.31 //int zoneID = pZone->getZoneID(); //if (zoneID==1005 || zoneID==1006) if (pZone->isNoPortalZone() || pZone->isMasterLair() || pZone->isCastle() || pZone->isHolyLand()) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } //*/ SubInventory* pInventoryItem = NULL; int invenID = 0; if (InventoryItemObjectID != 0 ) { //cout << "서브 인벤토리에서 사용 : " << InventoryItemObjectID << endl; CoordInven_t X, Y; pInventoryItem = dynamic_cast<SubInventory*>(pInventory->findItemOID(InventoryItemObjectID, X, Y )); TradeManager* pTradeManager = pZone->getTradeManager(); Assert(pTradeManager != NULL); if (pInventoryItem == NULL || pTradeManager->hasTradeInfo(pVampire->getName()) ) { //cout << "근데 서브 인벤토리가 없다." <<endl; executeSkillFailException(pVampire, getSkillType()); return; } pInventory = pInventoryItem->getInventory(); invenID = pInventoryItem->getItemID(); } Item* pItem = pInventory->getItem(X, Y); // 아이템이 없거나, 뱀파이어 포탈 아이템이 아니거나, OID가 틀리다면 기술 사용 불가 if (pItem == NULL || pItem->getItemClass() != Item::ITEM_CLASS_VAMPIRE_PORTAL_ITEM || pItem->getObjectID() != InvenObjectID) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } VampirePortalItem* pVampirePortalItem = dynamic_cast<VampirePortalItem*>(pItem); Assert(pVampirePortalItem != NULL); // 뱀파이어 포탈 아이템에 기록된 위치가 없을 경우에는 실패다. ZoneID_t zoneid = pVampirePortalItem->getZoneID(); ZoneCoord_t tx = pVampirePortalItem->getX(); ZoneCoord_t ty = pVampirePortalItem->getY(); if (zoneid == 0) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } // 얻어온 목표 존과 좌표를 검증한다. Zone* pTargetZone = getZoneByZoneID(zoneid); // 아담의 성지와 다른 존과는 연결되지 않는다. if (pZone->isHolyLand() != pTargetZone->isHolyLand()) { executeSkillFailException(pVampire, getSkillType()); return; } //cout << "타겟 존 포인터 획득 성공" << endl; VSRect* pRect = pTargetZone->getOuterRect(); if (!pRect->ptInRect(tx, ty)) { executeSkillFailException(pVampire, getSkillType()); //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; return; } //cout << "좌표 검증 성공" << endl; GCSkillToInventoryOK1 _GCSkillToInventoryOK1; SkillType_t SkillType = pSkillSlot->getSkillType(); SkillInfo* pSkillInfo = g_pSkillInfoManager->getSkillInfo(SkillType); int RequiredMP = decreaseConsumeMP(pVampire, pSkillInfo); bool bManaCheck = hasEnoughMana(pVampire, RequiredMP); bool bTimeCheck = verifyRunTime(pSkillSlot); bool bRangeCheck = checkZoneLevelToUseSkill(pVampire); //bool bHitRoll = HitRoll::isSuccessMagic(pVampire, pSkillInfo, pSkillSlot); bool bHitRoll = true; if (bManaCheck && bTimeCheck && bRangeCheck && bHitRoll) { decreaseMana(pVampire, RequiredMP, _GCSkillToInventoryOK1); SkillInput input(pVampire); SkillOutput output; computeOutput(input, output); // 각각의 존에다가 포탈을 더한다. ZONE_COORD s_coord; ZONE_COORD t_coord; s_coord.id = pZone->getZoneID(); s_coord.x = pVampire->getX(); s_coord.y = pVampire->getY(); t_coord.id = pTargetZone->getZoneID(); t_coord.x = tx; t_coord.y = ty; pZone->addVampirePortal(s_coord.x, s_coord.y, pVampire, t_coord); pTargetZone->addVampirePortal(t_coord.x, t_coord.y, pVampire, s_coord); _GCSkillToInventoryOK1.setSkillType(SkillType); _GCSkillToInventoryOK1.setObjectID(InvenObjectID); _GCSkillToInventoryOK1.setCEffectID(0); _GCSkillToInventoryOK1.setDuration(0); pPlayer->sendPacket(&_GCSkillToInventoryOK1); // 차지 수를 줄인다. pVampirePortalItem->setCharge(pVampirePortalItem->getCharge()-1); if (pVampirePortalItem->getCharge() > 0) { // 아직 차지가 남았다면 살려둔다. pVampirePortalItem->save(pVampire->getName(), STORAGE_INVENTORY, invenID, X, Y); } else { // 포탈 아이템의 차지가 다 소모되었다면 삭제시킨다. pInventory->deleteItem(X, Y); pVampirePortalItem->destroy(); // 아이템 포인터 자체가 지워지고, NULL이 되면, // 이펙트 내부에서의 아이템 포인터도 NULL이 되겠지... SAFE_DELETE(pVampirePortalItem); } pSkillSlot->setRunTime(output.Delay); } else { executeSkillFailNormal(pVampire, getSkillType(), NULL); } } catch(Throwable & t) { executeSkillFailException(pVampire, getSkillType()); } //cout << "TID[" << Thread::self() << "]" << getSkillHandlerName() << " End" << endl; __END_CATCH }
void CGAddMouseToInventoryHandler::execute(CGAddMouseToInventory* pPacket , Player* pPlayer) throw(ProtocolException, Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ Assert(pPacket != NULL); Assert(pPlayer != NULL); try { GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Assert(pGamePlayer != NULL); Creature* pCreature = pGamePlayer->getCreature(); Assert(pCreature != NULL); Assert(pCreature->isPC()); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature); Assert(pPC != NULL); Zone* pZone = pPC->getZone(); Assert(pZone != NULL); Inventory* pInventory = pPC->getInventory(); Assert(pInventory != NULL); Item* pItem = pPC->getExtraInventorySlot()->getItem(); bool Success = false; if (pItem == NULL) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } int invenID = 0; /* Commenting the SubInventory stuff, since it's not supported by the client we use SubInventory* pInventoryItem = NULL; int invenID = 0; if (pPacket->getInventoryItemObjectID() != 0 ) { // cout << "서브 인벤토리에 넣기 : " << pPacket->getInventoryItemObjectID() << endl; CoordInven_t X, Y; pInventoryItem = dynamic_cast<SubInventory*>(pInventory->findItemOID(pPacket->getInventoryItemObjectID(), X, Y )); TradeManager* pTradeManager = pZone->getTradeManager(); Assert(pTradeManager != NULL); if (pInventoryItem == NULL || pItem->getItemClass() == Item::ITEM_CLASS_SUB_INVENTORY || pTradeManager->hasTradeInfo(pPC->getName()) ) { // cout << "근데 서브 인벤토리가 없다." <<endl; GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } pInventory = pInventoryItem->getInventory(); invenID = pInventoryItem->getItemID(); } */ //Item::ItemClass itemClass = pItem->getItemClass(); //ItemType_t itemType = pItem->getItemType(); ObjectID_t itemObjectID = pItem->getObjectID(); CoordInven_t InvenX = pPacket->getInvenX(); CoordInven_t InvenY = pPacket->getInvenY(); if (InvenX >= pInventory->getWidth() || InvenY >= pInventory->getHeight() || itemObjectID != pPacket->getObjectID() || !pInventory->canAdding(InvenX, InvenY, pItem)) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } TPOINT pt; pt.x = 99; pt.y = 99; // 넣을려는 Inventory Slot의 Item을 받아온다. Item* pPrevItem = pInventory->searchItem(InvenX, InvenY , pItem, pt); // 그 장소에 아이템이 있다면 if (pPrevItem != NULL) { bool bisSame = true; // 아이템 클래스가 같을때 숫자를 올려 주고 마우스에 있는 것은 없앤다. if (canStack(pItem, pPrevItem)) { int MaxStack = ItemMaxStack[pItem->getItemClass()]; VolumeWidth_t ItemWidth = pItem->getVolumeWidth(); VolumeHeight_t ItemHeight = pItem->getVolumeHeight(); VolumeWidth_t InvenWidth = pInventory->getWidth(); VolumeWidth_t InvenHeight= pInventory->getHeight(); if ((InvenX + ItemWidth <= InvenWidth) && (InvenY + ItemHeight <= InvenHeight)) { for (int x = InvenX; x < (InvenX + ItemWidth); x++) { for (int y = InvenY; y < (InvenY + ItemHeight); y++) { if (pInventory->hasItem(x, y)) { if(pInventory->getItem(x,y) != pPrevItem ) { bisSame = false; break; } } else { bisSame = false; break; } } } } // 들어갈 아이템과 들어있는 아이템의 좌표가 꼭 일치 한다면? if(bisSame) { // 숫자가 9개를 넘으면 9개 될때까지만 Add 하고 나머지는 마우스에 달아둔다. if (pItem->getNum() + pPrevItem->getNum() > MaxStack) { ItemNum_t CurrentNum = pPrevItem->getNum(); ItemNum_t AddNum = pItem->getNum(); ItemNum_t NewNum = AddNum + CurrentNum - MaxStack; pPrevItem->setNum(MaxStack); pItem->setNum(NewNum); pInventory->increaseNum(MaxStack - CurrentNum); pInventory->increaseWeight(pItem->getWeight()* (MaxStack - CurrentNum)); //pPrevItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Num=%d, Storage=%d, StorageID=%d, X=%d, Y=%d", MaxStack, STORAGE_INVENTORY, invenID, InvenX, InvenY); pPrevItem->tinysave(pField); //pItem->save(pPC->getName(), STORAGE_EXTRASLOT, 0, 0, 0); // item저장 최적화. by sigi. 2002.5.13 sprintf(pField, "Num=%d, Storage=%d", NewNum, STORAGE_EXTRASLOT); pItem->tinysave(pField); Success = true; } else { pPC->deleteItemFromExtraInventorySlot(); pPrevItem->setNum(pPrevItem->getNum() + pItem->getNum()); pInventory->increaseNum(pItem->getNum()); pInventory->increaseWeight(pItem->getWeight()* pItem->getNum()); //pPrevItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Num=%d, Storage=%d, StorageID=%u, X=%d, Y=%d", pPrevItem->getNum(), STORAGE_INVENTORY, invenID, InvenX, InvenY); pPrevItem->tinysave(pField); pItem->destroy(); SAFE_DELETE(pItem); Success = true; } if (g_pVariableManager->getVariable(NETMARBLE_CARD_EVENT) != 0 && pPrevItem->getItemClass() == Item::ITEM_CLASS_MOON_CARD && pPrevItem->getItemType() == 2 && pPrevItem->getNum() == 99) { GCNoticeEvent gcNE; gcNE.setCode(NOTICE_EVENT_NETMARBLE_CARD_FULL); pGamePlayer->sendPacket(&gcNE); //cout << "gcNE sent" << endl; } if (pPrevItem->getItemClass() == Item::ITEM_CLASS_LUCKY_BAG && pPrevItem->getItemType() == 3 && pPrevItem->getNum() == 50 ) { GCDeleteInventoryItem gcDI; gcDI.setObjectID(pPrevItem->getObjectID()); pGamePlayer->sendPacket(&gcDI); pInventory->deleteItem(pPrevItem->getObjectID()); pPrevItem->destroy(); SAFE_DELETE(pPrevItem); Item* pNewItem = g_pItemFactoryManager->createItem(Item::ITEM_CLASS_EVENT_ITEM, 28, list<OptionType_t>()); pZone->registerObject(pNewItem); if (!pInventory->addItem(pt.x, pt.y, pNewItem) ) return; pNewItem->create(pPC->getName(), STORAGE_INVENTORY, 0, pt.x, pt.y); if (pNewItem != NULL ) { GCCreateItem gcCI; makeGCCreateItem(&gcCI, pNewItem, pt.x, pt.y); pGamePlayer->sendPacket(&gcCI); } } } else { pInventory->deleteItem(pPrevItem->getObjectID()); pPC->deleteItemFromExtraInventorySlot(); pPC->addItemToExtraInventorySlot(pPrevItem); pInventory->addItem(InvenX , InvenY , pItem); //pPrevItem->save(pPC->getName(), STORAGE_EXTRASLOT, 0, 0, 0); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Storage=%d", STORAGE_EXTRASLOT); pPrevItem->tinysave(pField); //pItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY); // item저장 최적화. by sigi. 2002.5.13 sprintf(pField, "Storage=%d, StorageID=%u, X=%d, Y=%d", STORAGE_INVENTORY, invenID, InvenX, InvenY); pItem->tinysave(pField); Success = true; } } else {// 아이템 클래스가 다르거나, 쌓이는 아이템이 아니라면. pInventory->deleteItem(pPrevItem->getObjectID()); pPC->deleteItemFromExtraInventorySlot(); pPC->addItemToExtraInventorySlot(pPrevItem); pInventory->addItem(InvenX , InvenY , pItem); //pPrevItem->save(pPC->getName(), STORAGE_EXTRASLOT, 0, 0, 0); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Storage=%d", STORAGE_EXTRASLOT); pPrevItem->tinysave(pField); //pItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY); // item저장 최적화. by sigi. 2002.5.13 sprintf(pField, "Storage=%d, StorageID=%u, X=%d, Y=%d", STORAGE_INVENTORY, invenID, InvenX, InvenY); pItem->tinysave(pField); Success = true; } } else { // 그 장소에 아이템이 없다면. //cout << "prevItem is NULL" << endl; // Inventory에 특정 아이템을 넣는다. pInventory->addItem(InvenX , InvenY , pItem); // 넣기에 성공하면 마우스에 달려있는 아이템을 없앤다. pPC->deleteItemFromExtraInventorySlot(); //pItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Storage=%d, StorageID=%u, X=%d, Y=%d", STORAGE_INVENTORY, invenID, InvenX, InvenY); pItem->tinysave(pField); Success = true; } if (Success) { TradeManager* pTradeManager = pZone->getTradeManager(); TradeInfo* pInfo = pTradeManager->getTradeInfo(pCreature->getName()); if (pInfo != NULL && pInfo->getStatus() == TRADE_FINISH) { GCTradeVerify gcTradeVerify; gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_MOUSE_TO_INVENTORY_OK); pPlayer->sendPacket(&gcTradeVerify); } // 트리 조각일 경우 if (pItem != NULL && pItem->getItemClass() == Item::ITEM_CLASS_EVENT_TREE) { ItemType_t itemtype = pItem->getItemType(); // 크리스마스 트리 조각이면 if (itemtype <= 11) { // 크리스마스 트리 조각이 맞춰지는지 본다. TPOINT pt = checkEventPuzzle(pPC, InvenX, InvenY, 0); if (pt.x != -1 && pt.y != -1 ) { // 맞춰진 트리 조각을 지운다. deleteInventoryItem(pInventory, pt.x, pt.y, pt.x + 2, pt.y + 3); // 트리를 생성한다. list<OptionType_t> optionType; Item* pTreeItem = g_pItemFactoryManager->createItem(Item::ITEM_CLASS_EVENT_TREE, 12, optionType); pZone->getObjectRegistry().registerObject(pTreeItem); pInventory->addItem(pt.x, pt.y, pTreeItem); pTreeItem->create(pPC->getName(), STORAGE_INVENTORY, invenID, pt.x, pt.y); // 클라이언트에 트리가 만들어졌다는 걸 알린다. GCCreateItem gcCreateItem; makeGCCreateItem(&gcCreateItem, pTreeItem, pt.x, pt.y); pGamePlayer->sendPacket(&gcCreateItem); } } // 크리스마스 트리 조각이면 else if (itemtype > 12 && itemtype <= 24) { // 크리스마스 트리 조각이 맞춰지는지 본다. TPOINT pt = checkEventPuzzle(pPC, InvenX, InvenY, 13); if (pt.x != -1 && pt.y != -1) { // 맞춰진 트리 조각을 지운다. deleteInventoryItem(pInventory, pt.x, pt.y, pt.x + 2, pt.y + 3); // 트리를 생성한다. list<OptionType_t> optionType; Item* pTreeItem = g_pItemFactoryManager->createItem(Item::ITEM_CLASS_EVENT_TREE, 25, optionType); pTreeItem->setQuestItem(); pZone->getObjectRegistry().registerObject(pTreeItem); pInventory->addItem(pt.x, pt.y, pTreeItem); pTreeItem->create(pPC->getName(), STORAGE_INVENTORY, invenID, pt.x, pt.y); // 클라이언트에 트리가 만들어졌다는 걸 알린다. GCCreateItem gcCreateItem; makeGCCreateItem(&gcCreateItem, pTreeItem, pt.x, pt.y); pGamePlayer->sendPacket(&gcCreateItem); } } // 크리스마스 트리 조각이면 else if (itemtype > 28 && itemtype <= 40) { // 크리스마스 트리 조각이 맞춰지는지 본다. TPOINT pt = checkEventPuzzle(pPC, InvenX, InvenY, 29); if (pt.x != -1 && pt.y != -1) { // 맞춰진 트리 조각을 지운다. deleteInventoryItem(pInventory, pt.x, pt.y, pt.x + 2, pt.y + 3); // 트리를 생성한다. list<OptionType_t> optionType; Item* pTreeItem = g_pItemFactoryManager->createItem(Item::ITEM_CLASS_EVENT_TREE, 41, optionType); pTreeItem->setQuestItem(); pZone->getObjectRegistry().registerObject(pTreeItem); pInventory->addItem(pt.x, pt.y, pTreeItem); pTreeItem->create(pPC->getName(), STORAGE_INVENTORY, invenID, pt.x, pt.y); // 클라이언트에 트리가 만들어졌다는 걸 알린다. GCCreateItem gcCreateItem; makeGCCreateItem(&gcCreateItem, pTreeItem, pt.x, pt.y); pGamePlayer->sendPacket(&gcCreateItem); } } } } else { //cout << "cannot add" << endl; GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); } } catch (Throwable & t) {} #endif // __GAME_SERVER__ __END_DEBUG_EX __END_CATCH }
void CGAddMouseToQuickSlotHandler::execute (CGAddMouseToQuickSlot* 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(); bool Success = false; if (pCreature->isSlayer()) { Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); InventorySlot* pExtraSlot = pSlayer->getExtraInventorySlot(); Item* pItem = pExtraSlot->getItem(); if (pItem == NULL) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } ObjectID_t ItemObjectID = pItem->getObjectID(); SlotID_t SlotID = pPacket->getSlotID(); Item::ItemClass IClass = pItem->getItemClass(); // 아이템의 ObjectID가 일치하는지 체크한다. if (ItemObjectID != pPacket->getObjectID()) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } // 벨트를 입고 있지 않다면 벨트에다 아이템을 더할 수가 없다. if (!pSlayer->isWear(Slayer::WEAR_BELT)) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } // 포션도 아니고, 탄창도 아니라면 더할 수가 없지. if (IClass != Item::ITEM_CLASS_POTION && IClass != Item::ITEM_CLASS_MAGAZINE && IClass != Item::ITEM_CLASS_EVENT_ETC && IClass != Item::ITEM_CLASS_KEY) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } if (IClass == Item::ITEM_CLASS_EVENT_ETC && pItem->getItemType() < 14 ) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } Item* pBelt = pSlayer->getWearItem(Slayer::WEAR_BELT); Inventory* pBeltInventory = ((Belt*)pBelt)->getInventory(); if (pBeltInventory->canAdding(SlotID, 0, pItem)) { // 현재 벨트에 있는 Item을 받아온다. Item* pPrevItem = pBeltInventory->getItem(SlotID, 0); // 지정한 자리에 아이템이 있다면... if (pPrevItem != NULL) { // 아이템이 완전히 같은 아이템이라면... if (isStackable(pItem) && isSameItem(pItem, pPrevItem)) { int MaxStack = ItemMaxStack[pItem->getItemClass()]; if (pItem->getNum() + pPrevItem->getNum() > MaxStack) { ItemNum_t CurrentNum = pPrevItem->getNum(); ItemNum_t AddNum = pItem->getNum(); ItemNum_t NewNum = AddNum + CurrentNum - MaxStack; pPrevItem->setNum(MaxStack); pItem->setNum(NewNum); pBeltInventory->increaseNum(MaxStack - CurrentNum); pBeltInventory->increaseWeight(pItem->getWeight()* (MaxStack - CurrentNum)); //pPrevItem->save(pSlayer->getName(), STORAGE_BELT, pBelt->getItemID(), SlotID, 0); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Num=%d, Storage=%d, StorageID=%lu, X=%d", MaxStack, STORAGE_BELT, pBelt->getItemID(), SlotID); pPrevItem->tinysave(pField); //pItem->save(pSlayer->getName(), STORAGE_EXTRASLOT, 0, 0, 0); // item저장 최적화. by sigi. 2002.5.13 sprintf(pField, "Num=%d, Storage=%d", NewNum, STORAGE_EXTRASLOT); pItem->tinysave(pField); Success = true; } else // 숫자가 9개를 넘지 않을 때. { pSlayer->deleteItemFromExtraInventorySlot(); pPrevItem->setNum(pPrevItem->getNum() + pItem->getNum()); pBeltInventory->increaseNum(pItem->getNum()); pBeltInventory->increaseWeight(pItem->getWeight()* pItem->getNum()); //pPrevItem->save(pSlayer->getName(), STORAGE_BELT , pBelt->getItemID(), SlotID, 0); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Num=%d, Storage=%d, StorageID=%lu, X=%d", pPrevItem->getNum(), STORAGE_BELT, pBelt->getItemID(), SlotID); pPrevItem->tinysave(pField); pItem->destroy(); SAFE_DELETE(pItem); Success = true; } } else // 클래스랑 타입이 같지 않을때 { // 마우스에 달려있는 아이템과 벨트에 있는 아이템을 제거한다. pSlayer->deleteItemFromExtraInventorySlot(); pBeltInventory->deleteItem(pPrevItem->getObjectID()); // 둘의 위치를 바꿔 준다. pSlayer->addItemToExtraInventorySlot(pPrevItem); pBeltInventory->addItem(SlotID , 0 , pItem); // DB에다가 저장을 한다. //pPrevItem->save(pSlayer->getName(), STORAGE_EXTRASLOT, 0, 0, 0); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Storage=%d", STORAGE_EXTRASLOT); pPrevItem->tinysave(pField); //pItem->save(pSlayer->getName(), STORAGE_BELT , pBelt->getItemID(), SlotID, 0); // item저장 최적화. by sigi. 2002.5.13 sprintf(pField, "Storage=%d, StorageID=%lu, X=%d", STORAGE_BELT, pBelt->getItemID(), SlotID); pItem->tinysave(pField); Success = true; } } else // 슬랏에 아무런 기존의 아이템이 없을때. { // Inventory에 특정 아이템을 넣는다. pBeltInventory->addItem(SlotID, 0 , pItem); // 넣기에 성공하면 마우스에 달려있는 아이템을 없앤다. pSlayer->deleteItemFromExtraInventorySlot(); //pItem->save(pSlayer->getName(), STORAGE_BELT, pBelt->getItemID(), SlotID, 0); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Storage=%d, StorageID=%lu, X=%d", STORAGE_BELT, pBelt->getItemID(), SlotID); pItem->tinysave(pField); Success = true; } } // end of if (pBeltInventory->canAdding(SlotID, 0, pItem)) } // if (pCreature->isSlayer()) else if (pCreature->isOusters()) { Ousters* pOusters = dynamic_cast<Ousters*>(pCreature); InventorySlot* pExtraSlot = pOusters->getExtraInventorySlot(); Item* pItem = pExtraSlot->getItem(); if (pItem == NULL) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } ObjectID_t ItemObjectID = pItem->getObjectID(); SlotID_t SlotID = pPacket->getSlotID(); Item::ItemClass IClass = pItem->getItemClass(); // 아이템의 ObjectID가 일치하는지 체크한다. if (ItemObjectID != pPacket->getObjectID()) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } Ousters::WearPart part = (SlotID > 2 ? Ousters::WEAR_ARMSBAND2 : Ousters::WEAR_ARMSBAND1); if (SlotID > 2 ) SlotID -= 3; // 해당 암스밴드가 없다 if (!pOusters->isWear(part)) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } // 푸파도 아니고, 콤포스메이도 아니라면 더할 수가 없지. if (IClass != Item::ITEM_CLASS_PUPA && IClass != Item::ITEM_CLASS_COMPOS_MEI && IClass != Item::ITEM_CLASS_EVENT_ETC ) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } if (IClass == Item::ITEM_CLASS_EVENT_ETC && pItem->getItemType() < 14 ) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } Item* pArmsband = pOusters->getWearItem(part); Inventory* pArmsbandInventory = ((OustersArmsband*)pArmsband)->getInventory(); if (pArmsbandInventory->canAdding(SlotID, 0, pItem)) { // 현재 벨트에 있는 Item을 받아온다. Item* pPrevItem = pArmsbandInventory->getItem(SlotID, 0); // 지정한 자리에 아이템이 있다면... if (pPrevItem != NULL) { // 아이템이 완전히 같은 아이템이라면... if (isSameItem(pItem, pPrevItem)) { int MaxStack = ItemMaxStack[pItem->getItemClass()]; if (pItem->getNum() + pPrevItem->getNum() > MaxStack) { ItemNum_t CurrentNum = pPrevItem->getNum(); ItemNum_t AddNum = pItem->getNum(); ItemNum_t NewNum = AddNum + CurrentNum - MaxStack; pPrevItem->setNum(MaxStack); pItem->setNum(NewNum); pArmsbandInventory->increaseNum(MaxStack - CurrentNum); pArmsbandInventory->increaseWeight(pItem->getWeight()* (MaxStack - CurrentNum)); //pPrevItem->save(pOusters->getName(), STORAGE_BELT, pArmsband->getItemID(), SlotID, 0); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Num=%d, Storage=%d, StorageID=%lu, X=%d", MaxStack, STORAGE_BELT, pArmsband->getItemID(), SlotID); pPrevItem->tinysave(pField); //pItem->save(pOusters->getName(), STORAGE_EXTRASLOT, 0, 0, 0); // item저장 최적화. by sigi. 2002.5.13 sprintf(pField, "Num=%d, Storage=%d", NewNum, STORAGE_EXTRASLOT); pItem->tinysave(pField); Success = true; } else // 숫자가 9개를 넘지 않을 때. { pOusters->deleteItemFromExtraInventorySlot(); pPrevItem->setNum(pPrevItem->getNum() + pItem->getNum()); pArmsbandInventory->increaseNum(pItem->getNum()); pArmsbandInventory->increaseWeight(pItem->getWeight()* pItem->getNum()); //pPrevItem->save(pOusters->getName(), STORAGE_BELT , pArmsband->getItemID(), SlotID, 0); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Num=%d, Storage=%d, StorageID=%lu, X=%d", pPrevItem->getNum(), STORAGE_BELT, pArmsband->getItemID(), SlotID); pPrevItem->tinysave(pField); pItem->destroy(); SAFE_DELETE(pItem); Success = true; } } else // 클래스랑 타입이 같지 않을때 { // 마우스에 달려있는 아이템과 벨트에 있는 아이템을 제거한다. pOusters->deleteItemFromExtraInventorySlot(); pArmsbandInventory->deleteItem(pPrevItem->getObjectID()); // 둘의 위치를 바꿔 준다. pOusters->addItemToExtraInventorySlot(pPrevItem); pArmsbandInventory->addItem(SlotID , 0 , pItem); // DB에다가 저장을 한다. //pPrevItem->save(pOusters->getName(), STORAGE_EXTRASLOT, 0, 0, 0); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Storage=%d", STORAGE_EXTRASLOT); pPrevItem->tinysave(pField); //pItem->save(pOusters->getName(), STORAGE_BELT , pArmsband->getItemID(), SlotID, 0); // item저장 최적화. by sigi. 2002.5.13 sprintf(pField, "Storage=%d, StorageID=%lu, X=%d", STORAGE_BELT, pArmsband->getItemID(), SlotID); pItem->tinysave(pField); Success = true; } } else // 슬랏에 아무런 기존의 아이템이 없을때. { // Inventory에 특정 아이템을 넣는다. pArmsbandInventory->addItem(SlotID, 0 , pItem); // 넣기에 성공하면 마우스에 달려있는 아이템을 없앤다. pOusters->deleteItemFromExtraInventorySlot(); //pItem->save(pOusters->getName(), STORAGE_BELT, pArmsband->getItemID(), SlotID, 0); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Storage=%d, StorageID=%lu, X=%d", STORAGE_BELT, pArmsband->getItemID(), SlotID); pItem->tinysave(pField); Success = true; } } // end of if (pArmsbandInventory->canAdding(SlotID, 0, pItem)) } // if (pCreature->isOusters()) // QuickSlot에 넣는 것을 실패 하였을때 실패 패킷을 날린다. if (!Success) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); } #endif // __GAME_SERVER__ __END_DEBUG_EX __END_CATCH }
void CGAddInventoryToMouseHandler::execute(CGAddInventoryToMouse* pPacket , Player* pPlayer) throw(ProtocolException, Error) { __BEGIN_TRY __BEGIN_DEBUG_EX #ifdef __GAME_SERVER__ GamePlayer* pGamePlayer = dynamic_cast<GamePlayer*>(pPlayer); Assert(pGamePlayer != NULL); Creature* pCreature = pGamePlayer->getCreature(); Assert(pCreature != NULL); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature); Assert(pPC != NULL); Zone* pZone = pPC->getZone(); Assert(pZone != NULL); if (pPC->getStore()->isOpen() ) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } CoordInven_t InvenX = pPacket->getX(); CoordInven_t InvenY = pPacket->getY(); ObjectID_t ItemOID = pPacket->getObjectID(); Inventory* pInventory = pPC->getInventory(); Assert(pInventory != NULL); int invenID = 0; /* Commenting the SubInventory stuff, since it's not supported by the client we use SubInventory* pInventoryItem = NULL; int invenID = 0; if (pPacket->getInventoryItemObjectID() != 0 ) { CoordInven_t X, Y; pInventoryItem = dynamic_cast<SubInventory*>(pInventory->findItemOID(pPacket->getInventoryItemObjectID(), X, Y )); if (pInventoryItem == NULL ) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } pInventory = pInventoryItem->getInventory(); invenID = pInventoryItem->getItemID(); } */ // 인벤토리 좌표를 넘어가면 곤란하다... if (InvenX >= pInventory->getWidth() || InvenY >= pInventory->getHeight()) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } Item* pItem = pInventory->getItem(InvenX, InvenY); Item* pExtraSlotItem = pPC->getExtraInventorySlotItem(); if (pPC->getStore()->hasItem(pItem ) ) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } // 더하고자 하는 아이템이 없거나, 이미 마우스에 뭔가가 붙어있다면 // 들 수 없다. if (pItem == NULL || pExtraSlotItem != NULL) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } // 일반적인 아이템 마우스 더하기 루틴 if (ItemOID != 0) { // OID가 일치하지 않으면 곤란하다... if (pItem->getObjectID() != ItemOID) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } pInventory->deleteItem(pItem->getObjectID()); pPC->addItemToExtraInventorySlot(pItem); //pItem->save(pPC->getName(), STORAGE_EXTRASLOT, 0, 0, 0); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Storage=%d, StorageID=0", STORAGE_EXTRASLOT); pItem->tinysave(pField); TradeManager* pTradeManager = pZone->getTradeManager(); TradeInfo* pInfo = pTradeManager->getTradeInfo(pCreature->getName()); if (pInfo != NULL && pInfo->getStatus() == TRADE_FINISH) { GCTradeVerify gcTradeVerify; gcTradeVerify.setCode(GC_TRADE_VERIFY_CODE_INVENTORY_TO_MOUSE_OK); pPlayer->sendPacket(&gcTradeVerify); } } // 겹치는 아이템 분리하기 루틴 else { // 겹치는 아이템이 아니거나, 현재 숫자가 2 미만이라면 분리할 수 없다. if (!isStackable(pItem) || pItem->getNum() < 2 || (pItem->getItemClass() == Item::ITEM_CLASS_MOON_CARD && pItem->getItemType() == 2 && pItem->getNum() == 99) || pPC->getStore()->hasItem(pItem) ) { GCCannotAdd _GCCannotAdd; _GCCannotAdd.setObjectID(pPacket->getObjectID()); pPlayer->sendPacket(&_GCCannotAdd); return; } // 기존의 아이템을 바탕으로 같은 아이템을 생성한다. Item::ItemClass IClass = pItem->getItemClass(); ItemType_t IType = pItem->getItemType(); const list<OptionType_t>& OType = pItem->getOptionTypeList(); Item* pNewItem = g_pItemFactoryManager->createItem(IClass, IType, OType); Assert(pNewItem != NULL); // 마우스에다 더할 아이템은 기존의 OID를 가져가고, // 인벤토리에 남을 아이템은 새로운 OID를 받아야 한다. Zone* pZone = pPC->getZone(); Assert(pZone != NULL); ObjectRegistry& OR = pZone->getObjectRegistry(); OR.registerObject(pNewItem); // 인벤토리에 남아있는 아이템의 숫자는 원래 숫자에서 1을 뺀 숫자가 된다. // 기존의 아이템은 마우스로 옮겨졌으므로, 숫자가 1이 된다. // 인벤토리에서 마우스로 옮겨진 아이템을 삭제하고, // 새로 생성된 아이템을 더한다. pInventory->deleteItem(pItem->getObjectID()); pPC->addItemToExtraInventorySlot(pItem); int NewNum = pItem->getNum() - 1; pNewItem->setNum(NewNum); pItem->setNum(1); pInventory->addItem(InvenX, InvenY, pNewItem); // 달라진 위치 정보를 세이브한다... //pItem->save(pPC->getName(), STORAGE_EXTRASLOT, 0, 0, 0); // item저장 최적화. by sigi. 2002.5.13 char pField[80]; sprintf(pField, "Num=%d, Storage=%d, StorageID=0", 1, STORAGE_EXTRASLOT); pItem->tinysave(pField); pNewItem->create(pPC->getName(), STORAGE_INVENTORY, invenID, InvenX, InvenY); //pNewItem->setNum(NewNum); // 위에서 했는데 또 하네. -_-; //pNewItem->save(pPC->getName(), STORAGE_INVENTORY, 0, InvenX, InvenY); // item저장 최적화. by sigi. 2002.5.13 sprintf(pField, "Num=%d, Storage=%d, StorageID=%u", NewNum, STORAGE_INVENTORY, invenID); pNewItem->tinysave(pField); // 클라이언트에게는 GCCreateItem 패킷을 이용해 // 인벤토리에 새로이(?) 생성된 아이템에 대한 정보를 보내준다. GCCreateItem gcCreateItem; gcCreateItem.setObjectID(pNewItem->getObjectID()); gcCreateItem.setItemClass((BYTE)pNewItem->getItemClass()); gcCreateItem.setItemType(pNewItem->getItemType()); gcCreateItem.setOptionType(pNewItem->getOptionTypeList()); gcCreateItem.setDurability(pNewItem->getDurability()); gcCreateItem.setSilver(pNewItem->getSilver()); gcCreateItem.setEnchantLevel(pNewItem->getEnchantLevel()); gcCreateItem.setItemNum(pNewItem->getNum()); gcCreateItem.setInvenX(InvenX); gcCreateItem.setInvenY(InvenY); pPlayer->sendPacket(&gcCreateItem); } #endif // __GAME_SERVER__ __END_DEBUG_EX __END_CATCH }
void CGUseMessageItemFromInventoryHandler::executeEventTree(CGUseMessageItemFromInventory* 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(); PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature); Inventory* pInventory = pPC->getInventory(); Zone* pZone = pPC->getZone(); CoordInven_t InvenX = pPacket->getX(); CoordInven_t InvenY = pPacket->getY(); Item* pItem = pInventory->getItem(InvenX, InvenY); ObjectID_t ItemObjectID = pItem->getObjectID(); MonsterType_t MType = 0; int time = 0; switch (pItem->getItemType() ) { case 12: MType = 482; time = g_pVariableManager->getVariable(CHRISTMAS_TREE_DECAY_TIME ) / 10; break; case 26: MType = 650; time = 21600; break; case 27: MType = 650; time = 43200; break; case 28: MType = 650; time = 86400; break; default: { filelog("EventTree.log", "이상한 아템을 썼다. : %s 가 %d", pPC->getName().c_str(), pItem->getItemType()); GCCannotUse _GCCannotUse; _GCCannotUse.setObjectID(pPacket->getObjectID()); pGamePlayer->sendPacket(&_GCCannotUse); } return; } // 타일에 스킬을 쓰는 것이라고 보고 쓸 수 있는지를 체크한다. // 안전지대에서는 사용할 수 없다. // 쓸 수 있는 아이템 타입인지 왁인한다. ItemType 이 12인 것만 사용할 수 있다. // 근처에(플레이어 주위의 5x5타일 이내) 다른 트리가 있다면 사용할 수 없다. if (!isAbleToUseTileSkill(pCreature ) || pZone->isMasterLair() || ItemObjectID != pPacket->getObjectID() || checkCorpse(pZone, MType, pPC->getX() - 2, pPC->getY() - 2, pPC->getX() + 2, pPC->getY() + 2 ) ) { GCCannotUse _GCCannotUse; _GCCannotUse.setObjectID(pPacket->getObjectID()); pGamePlayer->sendPacket(&_GCCannotUse); return; } // 성이면 성주 길드원만 쓸 수 있다. if (!pPC->isGOD() ) { if (pZone->isCastle() ) { if (!g_pCastleInfoManager->isCastleMember(pZone->getZoneID(), pPC ) ) { GCCannotUse _GCCannotUse; _GCCannotUse.setObjectID(pPacket->getObjectID()); pGamePlayer->sendPacket(&_GCCannotUse); return; } } // 성이 아닌 곳의 안전지대에선 절대 못 쓴다. else if (pZone->getZoneLevel(pCreature->getX(), pCreature->getY()) & SAFE_ZONE) { GCCannotUse _GCCannotUse; _GCCannotUse.setObjectID(pPacket->getObjectID()); pGamePlayer->sendPacket(&_GCCannotUse); return; } } /* // 트리를 존에 추가한다. (트리는 몬스터 시체를 이용한다) MonsterCorpse* pMonsterCorpse = new MonsterCorpse(482, pPacket->getMessage(), 2); Assert(pMonsterCorpse!=NULL); pZone->getObjectRegistry().registerObject(pMonsterCorpse); // 생성된 시체를 존에 추가한다. int delayTime = g_pVariableManager->getVariable(CHRISTMAS_TREE_DECAY_TIME); // by sigi. 2002.12.17 TPOINT pt = pZone->addItem(pMonsterCorpse, pPC->getX(), pPC->getY(), true, delayTime); // 6시간 뒤에 트리(시체)가 사라진다. if (pt.x == -1)*/ if (!createBulletinBoard(pZone, pPC->getX(), pPC->getY(), MType, pPacket->getMessage(), VSDateTime::currentDateTime().addSecs(time ) ) ) { GCCannotUse _GCCannotUse; _GCCannotUse.setObjectID(pPacket->getObjectID()); pGamePlayer->sendPacket(&_GCCannotUse); return; } // 사용한 아이템이므로 지워준다. pInventory->deleteItem(InvenX, InvenY); pItem->destroy(); SAFE_DELETE(pItem); // 아이템을 사용했다고 클라이언트에 알린다. GCUseOK gcUseOK; pGamePlayer->sendPacket(&gcUseOK); //pZone->broadcastPacket(pCreature->getX(), pCreature->getY(), &gcAddEffectToTile); #endif __END_DEBUG_EX __END_CATCH }
//////////////////////////////////////////////////////////////////////////////// // 액션을 실행한다. //////////////////////////////////////////////////////////////////////////////// void ActionTradeLairItem::execute(Creature * pCreature1 , Creature * pCreature2) throw(Error) { __BEGIN_TRY Assert(pCreature1 != NULL); Assert(pCreature2 != NULL); Assert(pCreature1->isNPC()); Assert(pCreature2->isPC()); if (m_Type <= 5 ) { SYSTEM_RETURN_IF_NOT(SYSTEM_MASTER_LAIR); } PlayerCreature* pPC = dynamic_cast<PlayerCreature*>(pCreature2); Assert(pPC != NULL); Player* pPlayer = pPC->getPlayer(); Assert(pPlayer != NULL); GCNPCResponse okpkt; pPlayer->sendPacket(&okpkt); StringStream message; /* GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage("아직 지원되지 않는 기능입니다"); pPlayer->sendPacket(&gcSystemMessage); */ //cout << "ActionTradeLairItem" << ":" << m_Type; Inventory* pInventory = pPC->getInventory(); // 먼저 아이템을 가지고 있는가를 체크한다. Item* pMasterItem = NULL; MonsterType_t MonsterType = 0; Item* pItem1 = NULL; bool bUpgrade = false; // 옵션에 따라서 다른 아이템을 검사해야 한다. // 코난 : 팬던트/ 비쥬만 체크한다. // 브리콜라카스: 테페즈 펜던트/비쥬만 체크해야 한다 // 카임 : 바토리 팬던트/비쥬만 체크해야 한다. if (m_Type == 0) // 코난, 비쥬 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 0); MonsterType = BATORI_TYPE; if (pMasterItem == NULL ) { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 2); MonsterType = TEPEZ_TYPE; if (pMasterItem == NULL ) { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8); //질드레 비쥬 MonsterType = GDR_TYPE; bUpgrade = true; } } } else if (m_Type == 1) // 코난, 팬던트 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 1); MonsterType = BATORI_TYPE; if (pMasterItem == NULL) { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 3); MonsterType = TEPEZ_TYPE; if (pMasterItem == NULL ) { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9); //질드레 펜던트 MonsterType = GDR_TYPE; bUpgrade = true; } } } else if (m_Type == 2) // 브리콜라카스, 비쥬 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 2); // if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8); //질드레 비쥬 MonsterType = TEPEZ_TYPE; } else if (m_Type == 3) // 브리콜라카스, 팬던트 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 3); // if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9); //질드레 펜던트 MonsterType = TEPEZ_TYPE; } else if (m_Type == 4) // 카임, 비쥬 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 0); // if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8); //질드레 비쥬 MonsterType = BATORI_TYPE; } else if (m_Type == 5) // 카임, 팬던트 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 1); // if (pMasterItem == NULL ) pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9); //질드레 펜던트 MonsterType = BATORI_TYPE; } else if (m_Type == 10) // 질드레, 비쥬 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 8); bUpgrade = true; MonsterType = GDR_TYPE; } else if (m_Type == 11) // 질드레, 팬던트 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 9); bUpgrade = true; MonsterType = GDR_TYPE; } else if (m_Type == 6) // 젬스톤이지롱~ { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 4); MonsterType = BATORI_TYPE; } else if (m_Type == 7) // 보름달~ { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 5); ItemMineInfo* pItemMineInfo; if (pPC->isSlayer() ) { Slayer* pSlayer = dynamic_cast<Slayer*>(pPC); Assert(pSlayer != NULL); Attr_t totalAttr = pSlayer->getTotalAttr(ATTR_BASIC); if (totalAttr <= 130 ) // 하드코딩 ㅜ.ㅠ pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(0); else if (totalAttr <= 210 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(1); else if (totalAttr <= 270 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(2); else if (totalAttr <= 300 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(3); else pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(4); } else if (pPC->isVampire() ) { Vampire* pVampire = dynamic_cast<Vampire*>(pPC); Assert(pVampire != NULL); Level_t level = pVampire->getLevel(); if (level <= 20 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(5); else if (level <= 40 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(6); else if (level <= 60 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(7); else if (level <= 90 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(8); else pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(9); } else if (pPC->isOusters() ) { Ousters* pOusters = dynamic_cast<Ousters*>(pPC); Assert(pOusters != NULL); Level_t level = pOusters->getLevel(); if (level <= 20 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(10); else if (level <= 40 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(11); else if (level <= 60 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(12); else if (level <= 90 ) pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(13); else pItemMineInfo = g_pItemMineInfoManager->getItemMineInfo(14); } else Assert(false); pItem1 = pItemMineInfo->getItem(); setItemGender(pItem1, (pPC->getSex()==FEMALE)?GENDER_FEMALE:GENDER_MALE); } else if (m_Type == 8) // 그믐달~ { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 6); if (pPC->isSlayer() ) { pItem1 = g_pItemMineInfoManager->getRandomItem(15, 32); } else if (pPC->isVampire() ) { pItem1 = g_pItemMineInfoManager->getRandomItem(33, 45); } else if (pPC->isOusters() ) { pItem1 = g_pItemMineInfoManager->getRandomItem(46, 61); } setItemGender(pItem1, (pPC->getSex()==FEMALE)?GENDER_FEMALE:GENDER_MALE); } else if (m_Type == 9) // 빨간색 복주머니 { pMasterItem = pInventory->findItem(Item::ITEM_CLASS_QUEST_ITEM, 7); if (pPC->isSlayer() ) { pItem1 = g_pItemMineInfoManager->getRandomItem(62, 81); } else if (pPC->isVampire() ) { pItem1 = g_pItemMineInfoManager->getRandomItem(82, 96); } else if (pPC->isOusters() ) { pItem1 = g_pItemMineInfoManager->getRandomItem(97, 112); } } else { // 거래를 위한 NPC의 Property가 잘못되었다. 이런 경우에는 // 운영팀으로 문의를 하면 바로 처리를 할 수 있다. GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NPC_ERROR )); pPlayer->sendPacket(&gcSystemMessage); GCNPCResponse response; response.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&response); return; } if (pMasterItem == NULL) { GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NO_LAIR_ITEM )); pPlayer->sendPacket(&gcSystemMessage); GCNPCResponse response; response.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&response); return; } Zone* pZone = pPC->getZone(); // if (MonsterType != 0 ) // 루팅표를 참조해서 아이템을 만들어오는 경우 if (pItem1 == NULL ) { QuestItemInfo* pItemInfo = dynamic_cast<QuestItemInfo*>(g_pQuestItemInfoManager->getItemInfo(pMasterItem->getItemType() )); Assert(pItemInfo!=NULL); /////////////////////////////////////////////////////////////////////////////// // 가장 난감한 부분 // 아이템을 랜덤하게 선택해야 한다. // 일단은 기본 아이템 하나로 한다. ////////////////////////////////////////////////////////////////////////////// const MonsterInfo* pMonsterInfo = g_pMonsterInfoManager->getMonsterInfo(MonsterType); TreasureList *pTreasureList = NULL; // 종족에 따라서 주는 아이템도 달라야 한다. if (pCreature2->isSlayer()) pTreasureList = pMonsterInfo->getSlayerTreasureList(); else if (pCreature2->isVampire()) pTreasureList = pMonsterInfo->getVampireTreasureList(); else if (pCreature2->isOusters()) pTreasureList = pMonsterInfo->getOustersTreasureList(); const list<Treasure*>& treasures = pTreasureList->getTreasures(); list<Treasure*>::const_iterator itr = treasures.begin(); ITEM_TEMPLATE it; for(; itr != treasures.end(); itr++) { Treasure* pTreasure = (*itr); it.ItemClass = Item::ITEM_CLASS_MAX; it.ItemType = 0; // QuestItem 마다 다른.. 옵션이 2개 붙을 확률 it.NextOptionRatio = pItemInfo->getBonusRatio(); //cout << "TradeLairItem: BonusRatio = " << it.NextOptionRatio << endl; if (pTreasure->getRandomItem(&it) ) { /* if (bUpgrade && isPossibleUpgradeItemType(it.ItemClass ) ) { it.ItemType = getUpgradeItemType(it.ItemClass, it.ItemType, 1); } */ pItem1 = g_pItemFactoryManager->createItem(it.ItemClass, it.ItemType, it.OptionType); Assert(pItem1 != NULL); } } if (pItem1 == NULL) { StringStream msg; msg << "ActionTradeLairItem: " << (int)it.ItemClass << ", " << (int)it.ItemType << ", " << (int)it.bCreateOption << ", " << getOptionTypeToString(it.OptionType); filelog("tradeLairItemBUG.txt", "%s", msg.toString().c_str()); GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_ITEM_CREATE_ERROR )); pPlayer->sendPacket(&gcSystemMessage); GCNPCResponse response; response.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&response); return; } } TPOINT pt; pItem1->setGrade(min(7,ItemGradeManager::Instance().getRandomBeadGrade())); pZone->registerObject(pItem1); // 만약 inventory에 공간이 있다면, 넣는다. if(pInventory->addItem(pItem1, pt)) { pItem1->create(pPC->getName(), STORAGE_INVENTORY, 0, pt.x, pt.y); GCCreateItem gcCreateItem; /* gcCreateItem.setObjectID(pItem1->getObjectID()); gcCreateItem.setItemClass(pItem1->getItemClass()); gcCreateItem.setItemType(pItem1->getItemType()); gcCreateItem.setOptionType(pItem1->getOptionTypeList()); gcCreateItem.setDurability(pItem1->getDurability()); gcCreateItem.setItemNum(pItem1->getNum()); gcCreateItem.setInvenX(pt.x); gcCreateItem.setInvenY(pt.y); gcCreateItem.setGrade(pItem1->getGrade());*/ makeGCCreateItem(&gcCreateItem, pItem1, pt.x, pt.y); pPlayer->sendPacket(&gcCreateItem); // ItemTraceLog 를 남긴다 if (pItem1 != NULL && pItem1->isTraceItem() ) { remainTraceLog(pItem1, pCreature1->getName(), pCreature2->getName(), ITEM_LOG_CREATE, DETAIL_EVENTNPC); } // 기존의 아이템을 없앤다 GCDeleteInventoryItem gcDeleteInventoryItem; gcDeleteInventoryItem.setObjectID(pMasterItem->getObjectID()); pPlayer->sendPacket(&gcDeleteInventoryItem); // 서버에서 없애준다. pInventory->deleteItem(pMasterItem->getObjectID()); // 좌표로 바꿔주면 좋을건데.. // ItemTraceLog 를 남긴다 if (pMasterItem != NULL && pMasterItem->isTraceItem() ) { remainTraceLog(pMasterItem, pCreature2->getName(), pCreature1->getName(), ITEM_LOG_DELETE, DETAIL_EVENTNPC); } pMasterItem->destroy(); SAFE_DELETE(pMasterItem); // 사용자에게 성공 메시지 출력 // StringStream message; // message << "성공적으로 교환되었습니다"; GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_TRADE_SUCCESS )); pPlayer->sendPacket(&gcSystemMessage); } else { // StringStream buf; // buf << "인벤토리에 공간이 부족합니다"; GCSystemMessage gcSystemMessage; gcSystemMessage.setMessage(g_pStringPool->getString(STRID_NOT_ENOUGH_INVENTORY_SPACE )); pPlayer->sendPacket(&gcSystemMessage); } GCNPCResponse response; response.setCode(NPC_RESPONSE_QUIT_DIALOGUE); pPlayer->sendPacket(&response); __END_CATCH }
void CGModifyNicknameHandler::execute (CGModifyNickname* 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); Inventory* pInventory = pPC->getInventory(); Assert(pInventory != NULL); GCNicknameVerify gcNV; ObjectID_t itemOID = pPacket->getItemObjectID(); EventGiftBox* pItem = NULL; if (itemOID != 0 ) { pItem = dynamic_cast<EventGiftBox*>(pInventory->getItemWithObjectID(itemOID )); if (pItem == NULL ) { filelog("Nickname.log", "[%s:%s] 아이템이 없거나 EventGiftBox가 아닙니다.", pPlayer->getID().c_str(), pPC->getName().c_str()); gcNV.setCode(NICKNAME_MODIFY_FAIL_NO_ITEM); pGamePlayer->sendPacket(&gcNV); return; } } else { PetInfo* pPetInfo = pPC->getPetInfo(); if (pPetInfo == NULL || pPetInfo->getPetType() != PET_PACKAGE ) { gcNV.setCode(NICKNAME_MODIFY_FAIL_NO_ITEM); pGamePlayer->sendPacket(&gcNV); return; } pPetInfo->setNickname(pPacket->getNickname()); pPetInfo->getPetItem()->savePetInfo(); sendPetInfo(pGamePlayer, true); gcNV.setCode(NICKNAME_MODIFY_OK); pGamePlayer->sendPacket(&gcNV); return; } switch (pItem->getItemType() ) { // 펫 닉네임 바꾸기 case 23 : { PetInfo* pPetInfo = pPC->getPetInfo(); if (pPetInfo == NULL ) { gcNV.setCode(NICKNAME_MODIFY_FAIL_NO_ITEM); pGamePlayer->sendPacket(&gcNV); return; } if (pPetInfo->getPetType() != PET_PACKAGE && pItem == NULL ) { gcNV.setCode(NICKNAME_MODIFY_FAIL_NO_ITEM); pGamePlayer->sendPacket(&gcNV); return; } pPetInfo->setNickname(pPacket->getNickname()); pPetInfo->getPetItem()->savePetInfo(); sendPetInfo(pGamePlayer, true); gcNV.setCode(NICKNAME_MODIFY_OK); pGamePlayer->sendPacket(&gcNV); if (pPetInfo->getPetType() != PET_PACKAGE ) { pInventory->deleteItem(itemOID); pItem->destroy(); SAFE_DELETE(pItem); GCUseOK gcOK; pGamePlayer->sendPacket(&gcOK); } return; } // 커스텀 닉네임 바꾸기 case 22 : case 25 : { NicknameInfo* pNickname = pPC->getNicknameBook()->getNicknameInfo(0); if (pNickname == NULL || pNickname->getNicknameType() != NicknameInfo::NICK_CUSTOM || pPacket->getNickname() == "" ) { gcNV.setCode(NICKNAME_MODIFY_FAIL_NO_ITEM); pGamePlayer->sendPacket(&gcNV); return; } if (pItem == NULL ) { gcNV.setCode(NICKNAME_MODIFY_FAIL_NO_ITEM); pGamePlayer->sendPacket(&gcNV); return; } // pPC->removeFlag(Effect::EFFECT_CLASS_CAN_MODIFY_NICKNAME_0); pNickname->setNickname(pPacket->getNickname()); Statement* pStmt = NULL; BEGIN_DB { pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement(); pStmt->executeQuery("UPDATE NicknameBook SET Nickname='%s' WHERE OwnerID='%s' AND nID=%u", getDBString(pNickname->getNickname()).c_str(), pPC->getName().c_str(), pNickname->getNicknameID()); SAFE_DELETE(pStmt); } END_DB(pStmt) gcNV.setCode(NICKNAME_MODIFY_OK); pGamePlayer->sendPacket(&gcNV); if (pItem->getItemType() == 22 ) { pInventory->deleteItem(itemOID); pItem->destroy(); SAFE_DELETE(pItem); GCUseOK gcOK; pGamePlayer->sendPacket(&gcOK); } if (pPC->getNickname() == pNickname ) { GCModifyNickname gcMN; gcMN.setObjectID(pPC->getObjectID()); gcMN.setNicknameInfo(pNickname); pPC->getZone()->broadcastPacket(pPC->getX(), pPC->getY(), &gcMN); } break; } // 닉네임 추가하기 case 24 : { if (pItem == NULL ) { gcNV.setCode(NICKNAME_MODIFY_FAIL_NO_ITEM); pGamePlayer->sendPacket(&gcNV); return; } NicknameInfo* pNickname = new NicknameInfo; pNickname->setNicknameID(pPC->getNicknameBook()->popNicknameID()); pNickname->setNicknameType(NicknameInfo::NICK_CUSTOM); pNickname->setNickname(pPacket->getNickname()); pPC->getNicknameBook()->setNicknameInfo(pNickname->getNicknameID(), pNickname); Statement* pStmt = NULL; BEGIN_DB { pStmt = g_pDatabaseManager->getConnection("DARKEDEN")->createStatement(); pStmt->executeQuery("INSERT INTO NicknameBook (nID, OwnerID, NickType, Nickname, Time) " "VALUES (%u, '%s', %u, '%s', now())", pNickname->getNicknameID(), pPC->getName().c_str(), pNickname->getNicknameType(), getDBString(pNickname->getNickname()).c_str()); SAFE_DELETE(pStmt); } END_DB(pStmt) gcNV.setCode(NICKNAME_MODIFY_OK); pGamePlayer->sendPacket(&gcNV); Packet* pNickList = pPC->getNicknameBook()->getNicknameBookListPacket(); pGamePlayer->sendPacket(pNickList); SAFE_DELETE(pNickList); pInventory->deleteItem(itemOID); pItem->destroy(); SAFE_DELETE(pItem); GCUseOK gcOK; pGamePlayer->sendPacket(&gcOK); break; } } #endif // __GAME_SERVER__ __END_DEBUG_EX __END_CATCH }