mirror of
https://github.com/UOX3DevTeam/UOX3
synced 2026-08-13 12:27:04 -04:00
398 lines
12 KiB
C++
398 lines
12 KiB
C++
#include "uox3.h"
|
|
#include "classes.h"
|
|
#include "CPacketSend.h"
|
|
#include "ObjectFactory.h"
|
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - SendTradeStatus()
|
|
//| Date - February 2, 2006
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Updates the status of the secure trade buttons (checked or unchecked) to both clients
|
|
//o------------------------------------------------------------------------------------------------o
|
|
void SendTradeStatus( CSocket *mSock, CSocket *nSock, CItem *tradeWindowOne, CItem *tradeWindowTwo )
|
|
{
|
|
CPSecureTrading cpstOne(( *tradeWindowOne ), ( tradeWindowOne->GetTempVar( CITV_MOREZ ) % 256), ( tradeWindowTwo->GetTempVar( CITV_MOREZ ) % 256 ));
|
|
cpstOne.Action( 2 );
|
|
mSock->Send( &cpstOne );
|
|
|
|
CPSecureTrading cpstTwo(( *tradeWindowTwo ), ( tradeWindowTwo->GetTempVar( CITV_MOREZ ) % 256), ( tradeWindowOne->GetTempVar( CITV_MOREZ ) % 256 ));
|
|
cpstTwo.Action( 2 );
|
|
nSock->Send( &cpstTwo );
|
|
}
|
|
void SendTradeStatus( CItem *tradeWindowOne, CItem *tradeWindowTwo )
|
|
{
|
|
CChar *p1 = FindItemOwner( tradeWindowOne );
|
|
CChar *p2 = FindItemOwner( tradeWindowTwo );
|
|
if( !ValidateObject( p1 ) || !ValidateObject( p2 ))
|
|
return;
|
|
|
|
CSocket *s1 = p1->GetSocket();
|
|
CSocket *s2 = p2->GetSocket();
|
|
if( s1 != nullptr && s2 != nullptr )
|
|
{
|
|
SendTradeStatus( s1, s2, tradeWindowOne, tradeWindowTwo );
|
|
}
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CreateTradeWindow()
|
|
//| Date - February 2, 2006
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Creates a TradeWindow and sends it to the clients
|
|
//o------------------------------------------------------------------------------------------------o
|
|
CItem *CreateTradeWindow( CSocket *mSock, CSocket *nSock, CChar *mChar )
|
|
{
|
|
CItem *mPack = mChar->GetPackItem();
|
|
if( !ValidateObject( mPack ))
|
|
{
|
|
mSock->SysMessage( 773 ); // Time to buy a backpack.
|
|
nSock->SysMessage( 1357, mChar->GetNameRequest( nSock->CurrcharObj() ).c_str() ); // %s doesn't have a backpack!
|
|
return nullptr;
|
|
}
|
|
|
|
CItem *tradeWindow = Items->CreateItem( nullptr, mChar, 0x1E5E, 1, 0, OT_ITEM, false );
|
|
if( !ValidateObject( tradeWindow ))
|
|
return nullptr;
|
|
|
|
tradeWindow->SetType( IT_TRADEWINDOW );
|
|
tradeWindow->SetCont( mChar );
|
|
tradeWindow->SetX( 0 );
|
|
tradeWindow->SetY( 0 );
|
|
tradeWindow->SetZ( 0 );
|
|
tradeWindow->SetDye( false );
|
|
tradeWindow->SetTempVar( CITV_MOREZ, 0 );
|
|
tradeWindow->SetDecayable( false );
|
|
|
|
tradeWindow->SendPackItemToSocket( mSock );
|
|
tradeWindow->SendPackItemToSocket( nSock );
|
|
|
|
return tradeWindow;
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - StartTrade()
|
|
//| Date - February 2, 2006
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Handles everything necesarry to start a secure trade
|
|
//o------------------------------------------------------------------------------------------------o
|
|
CItem *StartTrade( CSocket *mSock, CChar *nChar )
|
|
{
|
|
if( mSock == nullptr || !ValidateObject( nChar ))
|
|
return nullptr;
|
|
|
|
CChar *mChar = mSock->CurrcharObj();
|
|
CSocket *nSock = nChar->GetSocket();
|
|
|
|
if( !ValidateObject( mChar ) || nSock == nullptr )
|
|
return nullptr;
|
|
|
|
CItem *tradeWindowOne = CreateTradeWindow( mSock, nSock, mChar );
|
|
if( !ValidateObject( tradeWindowOne ))
|
|
return nullptr;
|
|
|
|
CItem *tradeWindowTwo = CreateTradeWindow( nSock, mSock, nChar );
|
|
if( !ValidateObject( tradeWindowTwo ))
|
|
{
|
|
tradeWindowOne->Delete();
|
|
return nullptr;
|
|
}
|
|
|
|
const SERIAL tw1Serial = tradeWindowOne->GetSerial();
|
|
const SERIAL tw2Serial = tradeWindowTwo->GetSerial();
|
|
|
|
tradeWindowOne->SetTempVar( CITV_MOREX, tw2Serial );
|
|
tradeWindowTwo->SetTempVar( CITV_MOREX, tw1Serial );
|
|
|
|
CPSecureTrading cpstOne(( *nChar ), tw1Serial, tw2Serial );
|
|
cpstOne.Name( nChar->GetNameRequest( mChar ));
|
|
mSock->Send( &cpstOne );
|
|
|
|
CPSecureTrading cpstTwo(( *mChar ), tw2Serial, tw1Serial );
|
|
cpstTwo.Name( mChar->GetNameRequest( nChar ));
|
|
nSock->Send( &cpstTwo );
|
|
|
|
CPWornItem toWear = ( *tradeWindowOne );
|
|
mSock->Send( &toWear );
|
|
nSock->Send( &toWear );
|
|
|
|
CPWornItem toWear2 = ( *tradeWindowTwo );
|
|
mSock->Send( &toWear2 );
|
|
nSock->Send( &toWear2 );
|
|
|
|
return tradeWindowOne;
|
|
}
|
|
|
|
bool ClearTradesFunctor( CBaseObject *a, UI32 &b, [[maybe_unused]] 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 )
|
|
{
|
|
// Find owner of trade window (each player has their own)
|
|
CChar *tradeWindowOwner = FindItemOwner( i );
|
|
if( ValidateObject( tradeWindowOwner ))
|
|
{
|
|
// Fetch backpack of owner of trade window
|
|
CItem *ownerPack = tradeWindowOwner->GetPackItem();
|
|
if( ValidateObject( ownerPack ))
|
|
{
|
|
// Iterate through all objects in trade window
|
|
GenericList<CItem *> *iCont = i->GetContainsList();
|
|
for( CItem *j = iCont->First(); !iCont->Finished(); j = iCont->Next() )
|
|
{
|
|
if( ValidateObject( j ))
|
|
{
|
|
// Delete pet transfer deeds - they only live inside trade windows
|
|
if( j->GetType() == IT_PETTRANSFERDEED )
|
|
{
|
|
j->Delete();
|
|
continue;
|
|
}
|
|
|
|
// Throw item from trade window back into owner's backpack
|
|
j->SetCont( ownerPack );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
i->Delete();
|
|
++b; // let's track how many we cleared
|
|
}
|
|
}
|
|
}
|
|
return retVal;
|
|
}
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - ClearTrades()
|
|
//| Date - February 2, 2006
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Loops through all items to clear any active trades
|
|
//o------------------------------------------------------------------------------------------------o
|
|
void ClearTrades( void )
|
|
{
|
|
UI32 b = 0;
|
|
ObjectFactory::GetSingleton().IterateOver( OT_ITEM, b, nullptr, &ClearTradesFunctor );
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CompleteTrade()
|
|
//| Date - February 2, 2006
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Handles everything necesarry to complete a trade
|
|
//o------------------------------------------------------------------------------------------------o
|
|
void CompleteTrade( CItem *tradeWindowOne, CItem *tradeWindowTwo, bool tradeSuccess )
|
|
{
|
|
CChar *p1 = FindItemOwner( tradeWindowOne );
|
|
CChar *p2 = FindItemOwner( tradeWindowTwo );
|
|
if( !ValidateObject( p1 ) || !ValidateObject( p2 ))
|
|
return;
|
|
|
|
CSocket *mSock = p1->GetSocket();
|
|
if( mSock != nullptr )
|
|
{
|
|
CPSecureTrading cpstOne(( *tradeWindowOne ));
|
|
cpstOne.Action( 1 );
|
|
mSock->Send( &cpstOne );
|
|
}
|
|
CSocket *nSock = p2->GetSocket();
|
|
if( nSock != nullptr )
|
|
{
|
|
CPSecureTrading cpstTwo(( *tradeWindowTwo ));
|
|
cpstTwo.Action( 1 );
|
|
nSock->Send( &cpstTwo );
|
|
}
|
|
|
|
CItem *bp1 = p1->GetPackItem();
|
|
CItem *bp2 = p2->GetPackItem();
|
|
if( ValidateObject( bp1 ) && ValidateObject( bp2 ))
|
|
{
|
|
CItem *i = nullptr;
|
|
GenericList<CItem *> *c1Cont = tradeWindowOne->GetContainsList();
|
|
for( i = c1Cont->First(); !c1Cont->Finished(); i = c1Cont->Next() )
|
|
{
|
|
if( ValidateObject( i ))
|
|
{
|
|
if( tradeSuccess )
|
|
{
|
|
if( i->GetType() == IT_PETTRANSFERDEED )
|
|
{
|
|
// Find serial of pet
|
|
SERIAL petSerial = i->GetTempVar( CITV_MORE );
|
|
if( petSerial != INVALIDSERIAL )
|
|
{
|
|
CChar *petChar = CalcCharObjFromSer( petSerial );
|
|
if( ValidateObject( petChar ))
|
|
{
|
|
// Transfer pet to other player
|
|
Npcs->FinalizeTransfer( petChar, p1, p2 );
|
|
}
|
|
}
|
|
|
|
// Delete pet transfer deed
|
|
i->Delete();
|
|
continue;
|
|
}
|
|
|
|
// Move transferred item to other player
|
|
i->SetCont( bp2 );
|
|
}
|
|
else
|
|
{
|
|
if( i->GetType() == IT_PETTRANSFERDEED )
|
|
{
|
|
// Delete pet transfer deed
|
|
i->Delete();
|
|
continue;
|
|
}
|
|
|
|
// Move item back to original player's backpack
|
|
i->SetCont( bp1 );
|
|
}
|
|
i->PlaceInPack();
|
|
}
|
|
}
|
|
GenericList<CItem *> *c2Cont = tradeWindowTwo->GetContainsList();
|
|
for( i = c2Cont->First(); !c2Cont->Finished(); i = c2Cont->Next() )
|
|
{
|
|
if( ValidateObject( i ))
|
|
{
|
|
if( tradeSuccess )
|
|
{
|
|
if( i->GetType() == IT_PETTRANSFERDEED )
|
|
{
|
|
// Find serial of pet
|
|
SERIAL petSerial = i->GetTempVar( CITV_MORE );
|
|
if( petSerial != INVALIDSERIAL )
|
|
{
|
|
CChar *petChar = CalcCharObjFromSer( petSerial );
|
|
if( ValidateObject( petChar ))
|
|
{
|
|
// Transfer pet to other player
|
|
Npcs->FinalizeTransfer( petChar, p2, p1 );
|
|
}
|
|
}
|
|
|
|
// Delete pet transfer deed
|
|
i->Delete();
|
|
continue;
|
|
}
|
|
|
|
// Move transferred item to other player
|
|
i->SetCont( bp1 );
|
|
}
|
|
else
|
|
{
|
|
if( i->GetType() == IT_PETTRANSFERDEED )
|
|
{
|
|
// Delete pet transfer deed
|
|
i->Delete();
|
|
continue;
|
|
}
|
|
|
|
// Move item back to original player's backpack
|
|
i->SetCont( bp2 );
|
|
}
|
|
i->PlaceInPack();
|
|
}
|
|
}
|
|
}
|
|
|
|
tradeWindowOne->Delete();
|
|
tradeWindowTwo->Delete();
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CancelTrade()
|
|
//| Date - February 2, 2006
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Cancels a secure trade
|
|
//o------------------------------------------------------------------------------------------------o
|
|
void CancelTrade( CItem *tradeWindowOne )
|
|
{
|
|
CItem *tradeWindowTwo = CalcItemObjFromSer( tradeWindowOne->GetTempVar( CITV_MOREX ));
|
|
if( !ValidateObject( tradeWindowTwo ))
|
|
return;
|
|
|
|
tradeWindowOne->SetTempVar( CITV_MOREZ, 0 );
|
|
tradeWindowTwo->SetTempVar( CITV_MOREZ, 0 );
|
|
SendTradeStatus( tradeWindowOne, tradeWindowTwo );
|
|
|
|
CompleteTrade( tradeWindowOne, tradeWindowTwo, false );
|
|
}
|
|
|
|
bool CPITradeMessage::Handle( void )
|
|
{
|
|
CItem *tradeWindowOne = CalcItemObjFromSer( tSock->GetDWord( 4 ));
|
|
if( ValidateObject( tradeWindowOne ))
|
|
{
|
|
CItem *tradeWindowTwo = nullptr;
|
|
switch( tSock->GetByte( 3 ))
|
|
{
|
|
case 0: // Start trade - Never happens, sent out by the server only.
|
|
break;
|
|
case 2: // Change check marks. Possibly conclude trade
|
|
tradeWindowTwo = CalcItemObjFromSer( tradeWindowOne->GetTempVar( CITV_MOREX ));
|
|
if( ValidateObject( tradeWindowTwo ))
|
|
{
|
|
tradeWindowOne->SetTempVar( CITV_MOREZ, tSock->GetByte( 11 ));
|
|
SendTradeStatus( tradeWindowOne, tradeWindowTwo );
|
|
if( tradeWindowOne->GetTempVar( CITV_MOREZ ) && tradeWindowTwo->GetTempVar( CITV_MOREZ ))
|
|
{
|
|
CompleteTrade( tradeWindowOne, tradeWindowTwo, true );
|
|
}
|
|
}
|
|
break;
|
|
case 1: // Cancel trade. Send each person cancel messages, move items.
|
|
CancelTrade( tradeWindowOne );
|
|
break;
|
|
default:
|
|
Console.Error( " Fallout of switch statement without default. trade.cpp, trademsg()" );
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool KillTradesFunctor( 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 = static_cast<CChar *>( i->GetCont() );
|
|
if( ValidateObject( k ))
|
|
{
|
|
CChar *mChar = static_cast<CChar *>( extraData );
|
|
if( k == mChar )
|
|
{
|
|
CancelTrade( i );
|
|
}
|
|
}
|
|
++b; // let's track how many we cleared
|
|
}
|
|
}
|
|
}
|
|
return retVal;
|
|
}
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - KillTrades()
|
|
//| Date - February 2, 2006
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Cancels any active trades associated with a character.
|
|
//o------------------------------------------------------------------------------------------------o
|
|
void KillTrades( CChar *i )
|
|
{
|
|
UI32 b = 0;
|
|
ObjectFactory::GetSingleton().IterateOver( OT_ITEM, b, i, &KillTradesFunctor );
|
|
}
|