mirror of
https://github.com/UOX3DevTeam/UOX3
synced 2026-08-13 12:27:04 -04:00
Fixed an issue where karma titles would inadvertently have the space behind the title trimmed before being displayed in paperdoll, resulting in erroneous display of title + name there Fixed an issue with a cooking script (js/skill/cooking/cooking.js) where sweet dough would not get consumed properly on cooking (Dragon Slayer) Updated C++ function calcRegionFromXY to work with CBaseObject instead of CChar, so it also works for Items Items now have current town region stored as an object property during runtime. This is calculated on load, when container property is updated, and when an item is picked up or dropped. The region is also accessible via the (read-only) JS Item property .region Added new JS Event to allow capturing button presses from the old-school gump displayed by client via packet 0x76, which was originally used by the old-school crafting menus in T2A. The requirement for this to work is that the gump in question must have a gumpID between 0x4000 and 0xffff (which can be set when manually creating a packet with this ID via JS), and the Event itself must be in the global script: onScrollingGumpPress( pSock, gumpID, buttonID ) Added new JS Event to allow better control over which names UOX3 sends to the client for characters: onNameRequest( myObj, requestedBy ) // return custom string, or return empty string/nothing/true/false to use default name Updated JS Events to also work for Items (previously only worked for Characters) onLightChange( myObj, lightLevel ) onTempChange( myObj, temp ) onWeatherChange( myObj, weatherType ) Adjusted default temperature for town regions with no weather systems defined from 0 to 20 degrees Celsius Updated some JS scripts (fishing.js, baking.js and cooking.js) to make use of GetTempTag/SetTempTag rather than GetTag/SetTag Added cancel-checks to targeting functions in command script for add-commands (js/commands/targeting/add.js) Updated get command script (js/commands/targeting/get.js) to allow retrieving region ID and name using 'get region Updated misc command script (js/commands/custom/misc-cmd.js) to add 'gettemptag and 'settemptag commands, used to retrieve/set temporary custom tags from/on objects Fixed a bug where Spirit Speak skill would be checked for race languages even if the race had LANGUAGEMIN defined as 0 (or not defined at all) Fixed an issue where players using regular UO client would get stuck in a black void after teleporting between worlds, by adding an additional character refresh after the teleport Fixed an issue where crafting tools for Blacksmithing and Carpentry would attempt to fetch the value of an incorrectly named INI setting to handle durability loss for the tools Added new setting under [settings] section of UOX.INI to control whether it should be possible to craft weapons from coloured ingots or not: CRAFTCOLOUREDWEAPONS=0/1 // If enabled(1), players can craft coloured weapons. Defaults to disabled(0) Fixed an issue where the correct ingots were not consumed when attempting to craft items using colored ingots Fixed a rogue debug message leftover in the scissor script
392 lines
12 KiB
C++
392 lines
12 KiB
C++
#include "uox3.h"
|
|
#include "classes.h"
|
|
#include "CPacketSend.h"
|
|
#include "ObjectFactory.h"
|
|
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void sendTradeStatus( CSocket *mSock, CSocket *nSock, CItem *tradeWindowOne, CItem *tradeWindowTwo )
|
|
//| 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 - CItem *CreateTradeWindow( CSocket *mSock, CSocket *nSock, CChar *mChar )
|
|
//| 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 );
|
|
nSock->sysmessage( 1357, mChar->GetNameRequest( nSock->CurrcharObj() ).c_str() );
|
|
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 - CItem *startTrade( CSocket *mSock, CChar *nChar )
|
|
//| 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 - void clearTrades( void )
|
|
//| 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 - void completeTrade( CItem *tradeWindowOne, CItem *tradeWindowTwo, bool tradeSuccess )
|
|
//| 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 - void cancelTrade( CItem *tradeWindowOne )
|
|
//| 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 - void killTrades( CChar *i )
|
|
//| 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 );
|
|
}
|