[FIXED] Bugfix: Getting onCollide to work.

Found a bug in UOX3? Or experienced a server crash? Perhaps you've noticed a broken feature? Post the details here!
Post Reply
Grimson
Developer
Posts: 802
Joined: Sat Jun 04, 2005 1:52 am
Location: Germany
Has thanked: 0
Been thanked: 0

Bugfix: Getting onCollide to work.

Post by Grimson »

After looking why onCollide doesn't work on some Items I compared the "void cMovement::HandleItemCollision( CChar *mChar, CSocket *mSock, SI16 oldx, SI16 oldy )" from movement.cpp with the "bool CPIDblClick::Handle( void )" function from cPlayerAction.cpp, because onUse does work for them. After comparing them I modified the following part of the HandleItemCollision:

Code: Select all

			if( EffRange )
			{
				if( !Magic->HandleFieldEffects( mChar, tItem, id ) )
				{
					if( id < 0x4000 )
					{
						UI16 targTrig		= tItem->GetScriptTrigger();
						cScript *toExecute	= JSMapping->GetScript( targTrig );
						if( toExecute != NULL )
							toExecute->OnCollide( mSock, mChar, tItem );
					}
				}
				HandleObjectCollisions( mSock, mChar, tItem, type );
				Magic->GateCollision( mSock, mChar, tItem, type );
			}
this way:

Code: Select all

			if( EffRange )
			{
				if( !Magic->HandleFieldEffects( mChar, tItem, id ) )
				{
					if( id < 0x4000 )
					{
						UI16 targTrig		= tItem->GetScriptTrigger();
						cScript *toExecute	= JSMapping->GetScript( targTrig );
						if( toExecute != NULL )
						{
							toExecute->OnCollide( mSock, mChar, tItem );
						}
						else if( JSMapping->GetEnvokeByType()->Check( static_cast<UI16>(type) ) )
						{
							envTrig = JSMapping->GetEnvokeByType()->GetScript( static_cast<UI16>(type) );
							cScript *envExecute = JSMapping->GetScript( envTrig );
							envExecute->OnCollide( mSock, mChar, tItem );
						}
						else if( JSMapping->GetEnvokeByID()->Check( id ) )
						{
							envTrig = JSMapping->GetEnvokeByID()->GetScript( id );
							cScript *envExecute = JSMapping->GetScript( envTrig );
							envExecute->OnCollide( mSock, mChar, tItem );
						}
					}
				}
				HandleObjectCollisions( mSock, mChar, tItem, type );
				Magic->GateCollision( mSock, mChar, tItem, type );
			}
And now it seems to work for all items. I'm not quite shure why, as I currently don't understand the different ways a script is associated to an item, but it works :).

Edit:
I nearly forgot, you also need to add this to the beginning of the HandleItemCollision function:

Code: Select all

UI16 envTrig		= 0;
giwo
Developer
Posts: 1780
Joined: Fri Jun 18, 2004 4:17 pm
Location: California
Has thanked: 0
Been thanked: 0

Post by giwo »

Ahh yes, I see what you have done.

When envoke is called by ID or Type, it does not actually ascribe a script number to an individual item object. That being the case, using GetScriptTrigger() doesn't work if you want to call the "envoke" script. So basically you are allowing items to be "envoked" by colliding with them, rather than simply using them (as exists now).
Scott
User avatar
Xuri
Site Admin
Posts: 3704
Joined: Mon Jun 02, 2003 9:11 am
Location: Norway
Has thanked: 48 times
Been thanked: 8 times
Contact:

Post by Xuri »

There are probably other places where that change could be beneficial, though I can't really seem to conjure up any examples right now. :P
-= Ho Eyo He Hum =-
Grimson
Developer
Posts: 802
Joined: Sat Jun 04, 2005 1:52 am
Location: Germany
Has thanked: 0
Been thanked: 0

Post by Grimson »

And more problems with onCollide. It doesn't work on NPCs because of this line in the "bool cScript::OnCollide( CSocket *tSock, CChar *objColliding, CBaseObject *objCollideWith )" function in "cScript.cpp":

Code: Select all

	if( !ValidateObject( objColliding ) || !ValidateObject( objCollideWith ) || tSock == NULL )
		return false;
There it expects a valid socket, but NPCs don't have one.

So there are currently two options I was thinking of.

The first one is removing the check and leave checking for a valid socket to the scripts.

The second is changing the call in the "void cMovement::OutputShoveMessage( CChar *c, CSocket *mSock )" function in movement.cpp so that it sends the players socket when the character the player collided with is an NPC, like this:

Code: Select all

	for( ourChar = regChars->First(); !regChars->Finished(); ourChar = regChars->Next() )
	{
		if( !ValidateObject( ourChar ) )
			continue;
		if( ourChar != c && ( ourChar->IsNpc() || isOnline( (*ourChar) ) ) )
		{
			if( ourChar->GetX() == x && ourChar->GetY() == y && ourChar->GetZ() == z )
			{
				if( toExecute != NULL )
					toExecute->OnCollide( mSock, c, ourChar );
				UI16 tTrig		= ourChar->GetScriptTrigger();
				cScript *tExec	= JSMapping->GetScript( tTrig );
				if( tExec != NULL )
				{
					if( ourChar->IsNpc() )
						tExec->OnCollide( mSock, c, ourChar );
					else
						tExec->OnCollide( calcSocketObjFromChar( ourChar ), ourChar, c );
				}

				if( !ourChar->IsDead() && !c->IsDead() )
				{
					if( ourChar->GetVisible() == VT_TEMPHIDDEN || ourChar->GetVisible() == VT_INVISIBLE )
					{
						mSock->sysmessage( 1383, ourChar->GetName().c_str() );
						c->SetStamina( UOX_MAX( c->GetStamina() - 4, 0 ) );
					}
					else if( ourChar->GetCommandLevel() < CNS_CMDLEVEL )
					{
						mSock->sysmessage( 1384 );
						c->SetStamina( UOX_MAX( c->GetStamina() - 4, 0 ) );
					}
				}
			}
		}
	}
	regChars->Pop();
I'm currently testing the second one.
User avatar
Xuri
Site Admin
Posts: 3704
Joined: Mon Jun 02, 2003 9:11 am
Location: Norway
Has thanked: 48 times
Been thanked: 8 times
Contact:

Post by Xuri »

Is this fixed (but not on CVS) - or are you still working on it?
-= Ho Eyo He Hum =-
Grimson
Developer
Posts: 802
Joined: Sat Jun 04, 2005 1:52 am
Location: Germany
Has thanked: 0
Been thanked: 0

Post by Grimson »

Xuri wrote:Is this fixed (but not on CVS) - or are you still working on it?
The above works, when you shove an NPC out of the way onCollide() will be called in it's attached script.

But I'm not to pleased with it, as I think onCollide() should also be called when you run into an NPC without shoving it out of the way. However I want to wait for the next UOX3 version with the changed mapstuff before making any changes to the movement code.
User avatar
Xuri
Site Admin
Posts: 3704
Joined: Mon Jun 02, 2003 9:11 am
Location: Norway
Has thanked: 48 times
Been thanked: 8 times
Contact:

Post by Xuri »

My observations on the onCollide event as of 0.98-3.1c (CVS version):

-An onCollide script only executes for the ITEM being walked on, not for the character doing the walking. So the script has to be attached to the item, not the character, which isn't really an ideal solution in my opinion. Ideally we'd have two seperate events - one for the character doing the colliding, and one for an object which is being collided with. (Though the other "party" should still be accessible in the event, no matter if it's executed for the "collider" or the "collidee".

-OnCollide for characters works differently, in that it executes for the character doing the walking if that character collides with another character. Which is good. But it will only execute if the character actually "shoves" another character (looses stamina, etc). So it will not run for GM characters. Unable to test if this executes for NPCs colliding with other characters, since NPCs very seldom (if every) actually collide with other NPCs or players.

-The onCollide script will also execute for a character if another character collides with him (regardless of whether the other character has an onCollide script attached or not) - but as said - only if there's any "shoving" taking place. Which again rules out GM characters. Also, does not run for NPCs being collided with.
-= Ho Eyo He Hum =-
Post Reply