bool clearTradesFunctor( CBaseObject *a, UI32 &b, void *extraData ) { bool retVal = true; if( ValidateObject( a ) && a->CanBeObjType( OT_ITEM ) ) { // Body of the functor goes here CItem *i = static_cast< CItem * >(a); if( ValidateObject( i ) ) { if( i->GetType() == IT_TRADEWINDOW ) { CChar *k = FindItemOwner( i ); if( ValidateObject( k ) ) { CItem *p = k->GetPackItem(); if( ValidateObject( p ) ) { CDataList< CItem * > *iCont = i->GetContainsList(); for( CItem *j = iCont->First(); !iCont->Finished(); j = iCont->Next() ) { if( ValidateObject( j ) ) j->SetCont( p ); } } } i->Delete(); ++b; // let's track how many we cleared } } } return retVal; }
//o---------------------------------------------------------------------------o //| Function : void buyItem(CSocket *mSock) //| Date : Unknown //| Programmer : UOX3 DevTeam //o---------------------------------------------------------------------------o //| Purpose : Called when player buys an item from a vendor //o---------------------------------------------------------------------------o bool CPIBuyItem::Handle(void) { UI16 i; UI32 playergoldtotal, goldtotal = 0; bool soldout = false, clear = false; CChar *mChar = tSock->CurrcharObj(); CItem *p = mChar->GetPackItem(); if (!ValidateObject(p)) return true; ITEMLIST bitems; std::vector<UI08> layer; std::vector<UI16> amount; // vector for storing all objects that actually end up in user backpack std::vector< CItem * > boughtItems; CChar *npc = calcCharObjFromSer(tSock->GetDWord(3)); UI16 itemtotal = static_cast<UI16>((tSock->GetWord(1) - 8) / 7); if (itemtotal > 511) return true; boughtItems.reserve(itemtotal); bitems.resize(itemtotal); amount.resize(itemtotal); layer.resize(itemtotal); int baseOffset = 0; for (i = 0; i < itemtotal; ++i) { baseOffset = 7 * i; layer[i] = tSock->GetByte(8 + baseOffset); bitems[i] = calcItemObjFromSer(tSock->GetDWord(9 + baseOffset)); amount[i] = tSock->GetWord(13 + baseOffset); goldtotal += (amount[i] * (bitems[i]->GetBuyValue())); } bool useBank = (goldtotal >= static_cast<UI32>(cwmWorldState->ServerData()->BuyThreshold())); if (useBank) playergoldtotal = GetBankCount(mChar, 0x0EED); else playergoldtotal = GetItemAmount(mChar, 0x0EED); if (playergoldtotal >= goldtotal || mChar->IsGM()) { for (i = 0; i < itemtotal; ++i) { if (bitems[i]->GetAmount() < amount[i]) soldout = true; // Check if onBuyFromVendor JS event is present for each item being purchased // If true, and a return false has been returned from the script, halt the purchase UI16 targTrig = bitems[i]->GetScriptTrigger(); cScript *toExecute = JSMapping->GetScript(targTrig); if (toExecute != NULL) if (toExecute->OnBuyFromVendor(tSock, npc, bitems[i])) { bitems.clear(); //needed??? return true; } } if (soldout) { npc->TextMessage(tSock, 1336, TALK, false); clear = true; } else { if (mChar->IsGM()) npc->TextMessage(NULL, 1337, TALK, false, mChar->GetName().c_str()); else { if (goldtotal == 1) npc->TextMessage(NULL, 1338, TALK, false, mChar->GetName().c_str(), goldtotal); else npc->TextMessage(NULL, 1339, TALK, false, mChar->GetName().c_str(), goldtotal); Effects->goldSound(tSock, goldtotal); } clear = true; if (!mChar->IsGM()) if (useBank) DeleteBankItem(mChar, goldtotal, 0x0EED); else DeleteItemAmount(mChar, goldtotal, 0x0EED); CItem *biTemp; CItem *iMade = NULL; UI16 j; for (i = 0; i < itemtotal; ++i) { biTemp = bitems[i]; iMade = NULL; if (biTemp->GetAmount() > amount[i]) { if (biTemp->isPileable()) { iMade = Items->DupeItem(tSock, biTemp, amount[i]); if (iMade != NULL) { iMade->SetCont(p); iMade->PlaceInPack(); boughtItems.push_back(iMade); } } else { for (j = 0; j < amount[i]; ++j) { iMade = Items->DupeItem(tSock, biTemp, 1); if (iMade != NULL) { iMade->SetCont(p); iMade->PlaceInPack(); boughtItems.push_back(iMade); } } } biTemp->IncAmount(-amount[i], true); biTemp->SetRestock(biTemp->GetRestock() + amount[i]); } else { switch(layer[i]) { case 0x1A: // Sell Container if (biTemp->isPileable()) { iMade = Items->DupeItem(tSock, biTemp, amount[i]); if (iMade != NULL) { iMade->SetCont(p); iMade->PlaceInPack(); boughtItems.push_back(iMade); } } else { for (j = 0; j < amount[i]; ++j) { iMade = Items->DupeItem(tSock, biTemp, 1); if (iMade != NULL) { iMade->SetCont(p); iMade->PlaceInPack(); boughtItems.push_back(iMade); } } } biTemp->IncAmount(-amount[i], true); biTemp->SetRestock(biTemp->GetRestock() + amount[i]); break; case 0x1B: // Bought Container if (biTemp->isPileable()) { biTemp->SetCont(p); boughtItems.push_back(biTemp); } else { for (j = 0; j < amount[i]-1; ++j) { iMade = Items->DupeItem(tSock, biTemp, 1); if (iMade != NULL) { iMade->SetCont(p); iMade->PlaceInPack(); boughtItems.push_back(iMade); } } biTemp->SetCont(p); biTemp->SetAmount(1); boughtItems.push_back(biTemp); } break; default: Console.Error(" Fallout of switch statement without default. vendor.cpp, buyItem()"); break; } } } for (i = 0; i < boughtItems.size(); ++i) { if (boughtItems[i]) { cScript *toGrab = JSMapping->GetScript(boughtItems[i]->GetScriptTrigger()); if (toGrab != NULL) toGrab->OnBoughtFromVendor(tSock, npc, boughtItems[i]); } } } } else npc->TextMessage(NULL, 1340, TALK, false); if (clear) { CPBuyItem clrSend; clrSend.Serial(tSock->GetDWord(3)); tSock->Send(&clrSend); } return true; }