mirror of
https://github.com/UOX3DevTeam/UOX3
synced 2026-08-13 12:27:04 -04:00
Misc cleanup and standardization of style and naming conventions in code and scripts Added missing code for showing race in paperdoll based on ini setting Players can no longer use Polymorph spell while incognitoed, or while under effect of tribal paint Players can no longer use Incognito spell while polymorphed, or while under the effects of tribal paint Facial hair is now removed from players who are under the effects of Incognito spell that changes their gender for female
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, 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 );
|
|
}
|