RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

NPC Speech Triggers & [Go <city> locations

Rakshasas

Wanderer
NPC Speech Triggers & [Go <city> locations

I'm developing a new character region on my shard, it's just an area where players can get set up before they step out into the world.

I decided that instead of using some kind of tele stone, I'd make an automated counselor do that kind of stuff. It would do this via speech keywords. I've done all that already, but I'm not sure my method is the best. Mainly because you can only say the keyword, and not mix it with out words.

The keyword to travel is, travel. I feel like doing destination as well and perhaps make a context menu for this as well. When the keyword is spoken a dialog will open with a city selection. But like I said earlier I'm not happy with the way I coded it because you can't say something like "I want to travel." You can just say "travel" and nothing more.

The next thing on the list is to have them teleport you to a city. This I could do easily but I want to take a slightly more complicated route. I'd like it to use the same x,y,z coords that are default for the city. If you yourself typed [Go Britain, or [Go Ocllo...

That way if I ever change that specific location, it will be changed in this script, or any other script I plan to use.

Before I give the NPC script for the keyword question, it's a good idea to mention that I tried adding the wildcard "*" before and after each word. Turns out after doing that, it wanted me to include that in the speech.

So I'd have to say *travel* :/

Ok so here is the NPC script:
PHP:
using System;
using System.Collections;
using Server.Items;
using Server.ContextMenus;
using Server.Misc;
using Server.Network;
using Server.Gumps;

namespace Server.Mobiles
{
	public class NewCharAide : BaseCreature
	{
		[Constructable]
		public NewCharAide() : base( AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4 )
		{
			SpeechHue = Utility.RandomDyedHue();
			Hue = Utility.RandomSkinHue();
			Title = "The New Character Aide";
			CantWalk = true;
			
			AddItem( new CounselorRobe() );

			if ( this.Female = Utility.RandomBool() )
			{
				Body = 0x191;
				Name = NameList.RandomName( "female" );
				Hue=1002;

			}
			else
			{
				Body = 0x190;
				Name = NameList.RandomName( "male" );
				Hue=1002;
			}

			SetStr( 100 );
			SetDex( 100 );
			SetInt( 100 );
			
			Fame = 0;
			Karma = 10000;

			Item hair = new Item( Utility.RandomList( 0x203B, 0x2049, 0x2048, 0x204A ) );
			hair.Hue = Utility.RandomNondyedHue();
			hair.Layer = Layer.Hair;
			hair.Movable = false;
			AddItem( hair );
		}
		

		public NewCharAide( Serial serial ) : base( serial )
		{
		}
		
		public override bool HandlesOnSpeech( Mobile from )
		{
			if ( from.InRange( this.Location, 3 ) )
			return true;
			
			return base.HandlesOnSpeech( from );
		}

		public override void OnSpeech( SpeechEventArgs args ) 
		{ 
			string said = args.Speech.ToLower();
			Mobile from = args.Mobile;
			switch ( said )
			{
				case ( "hi" ):
				{
						goto case "hail";
				}
				case ( "hello" ):
				{
						goto case "hail";
				}
				case ( "hail" ):
				{
						Say( String.Format( "Hail, {0}!", args.Mobile.Name ) ); //Npc says hello to the player
						Say( String.Format( "{0}, speak Travel if you are ready to depart.", args.Mobile.Name ) ); //Npc says hello to the player 
						break;
				}
				case ( "travel" ):
				{
						Say( String.Format( "Where would you like to go?" ) ); //Npc asks for destination 
						from.CloseGump( typeof( CityDialog ) );
						from.SendGump( new CityDialog( from, this ) );
						break;
				}									
			}
			//if ( args.Speech.ToLower().IndexOf( "hello" ) >= 0 || args.Speech.ToLower().IndexOf( "hail" ) >= 0 )	
		} 
	
		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );

			writer.Write( (int) 0 ); // version
		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );

			int version = reader.ReadInt();
		}
	}
}

PHP:
 using System;
using Server;
using Server.Accounting;
using System.Collections;
using Server.Gumps; 
using Server.Items; 
using Server.Network;
using Server.Mobiles; 
using Server.Prompts;

namespace Server.Gumps 
{ 
   public class CityDialog : Gump 
   {
   		public static readonly LocationTree Felucca = new LocationTree( "felucca.xml", Map.Felucca );
   		NewCharAide m_NCA;
   	
   		public CityDialog( Mobile from, NewCharAide nca ) : base( 30, 30 )
		{		
			m_NCA = nca;
			AddPage( 0 );
				
			int Xpos = 0; int Ypos = 0;
			int width = 330; int height = 280;
			AddBackground( Xpos, Ypos, width, height, 83 );
			//AddAlphaRegion( Xpos, Ypos, width + 10, height );
			Xpos = 30; Ypos = 10;
			AddLabel( Xpos, Ypos, 33, "Where do you want to go?" );
			
			//Gather Information Area
			Xpos = 40; Ypos = 53; width = 140; height = 15;	
			AddButton( Xpos - 17, Ypos , 2117, 2118, 1, GumpButtonType.Reply, 0 ); // Goto Britain
			AddLabel( Xpos, Ypos, 10, "Britain" );
			
			Ypos +=20;
			AddButton( Xpos - 17, Ypos , 2117, 2118, 2, GumpButtonType.Reply, 0 ); //Goto Ocllo
			AddLabel ( Xpos, Ypos, 10, "Ocllo" );
			
			Ypos +=20;
			AddButton( Xpos - 17, Ypos, 2117, 2118, 3, GumpButtonType.Reply, 0 ); // Goto Trinsic
			AddLabel( Xpos, Ypos, 10, "Trinsic" );
		}

		public override void OnResponse( NetState sender, RelayInfo info )
		{		
			Mobile from = sender.Mobile;
			
			switch( info.ButtonID )
			{
				case 1: // Goto Britain
				{
					m_NCA.Say( String.Format( "Enjoy Britain {0}!", from.Name ) );
					break;
				}
				case 2: // Gogo Ocllo
				{
					m_NCA.Say( String.Format( "Enjoy Ocllo {0}!", from.Name ) );
					break;
				}
				case 3: // Goto Trinsic
				{
					m_NCA.Say( String.Format( "Enjoy Trinsic {0}!", from.Name ) );
					//from.MoveToWorld ( "Trinsic", from.Map );
					
					break;
				}
			}
		}
	}
}

Before I ask about context menus I'm going to take a look in the distro scripts.
 

David

Moderate
Let me admit right off that I have not really read your script... this is kind of a quicky answer to what I think you are asking. ;) If I'm off base, please ignore me.

I have checked for spoken text two ways, this first one checks for actual embedded text, not uo keywords. This is part of an old beggar script I helped develop. Note the args.Speech.ToLower().IndexOf
Code:
		public override void OnSpeech( SpeechEventArgs args ) 
		{ 
			if ( m_Done ) return;

			if ( args.Mobile.InRange( this, 2 ) ) //if a player is within 2 tiles of the NPC 
			{ 
				if ( args.Speech.ToLower().IndexOf( "name" ) >= 0 ) 
				{
					this.Direction =  GetDirectionTo( args.Mobile.Location );
					Say( String.Format( "My name is {0}, in your service.", this.Name ) ); //Npc tells the player it's name
					this.Animate( 32, 5, 1, true, false, 0 ); // Bow
				}

				else if ( args.Speech.ToLower().IndexOf( "hello" ) >= 0 || args.Speech.ToLower().IndexOf( "hail" ) >= 0 ) //Checks to see if the player says Hail or Hello 
					Say( String.Format( "Hail " ) ); //Npc says hello to the player 
//
// ...keeps on going...
//
This following code is the same section (abbreviated) from a conversational npc. The ReplyList referance is pulling text from an xml file, just know that I pass it the keyword and it returns a phrase from it's list. This line int[] keywords = e.Keywords; actually gives me the keywords embedded in the spoken text.
Code:
		public override void OnSpeech ( SpeechEventArgs e )
		{
			base.OnSpeech( e );

			Mobile from = e.Mobile;
			int[] keywords = e.Keywords;
			string lc_speech = (e.Speech).ToLower();

			if ( !e.Handled && from.InRange( this, 3 ) )
			{
				// Parse keywords
				for ( int i = 0; !e.Handled && i < keywords.Length; ++i )
				{
					string reply = ReplyList.RandomReply( keywords[i] );
					Say( reply );

					e.Handled = true;
				}

hope that helps
 

Rakshasas

Wanderer
Thanks that did the trick :) It's too bad I couldn't keep with the switch case structure though. It seems easier to maintain/add new words.

Then again I'd rather use your second method, with the XML file. I think I'll have to start learning XML now :)

Thanks again David!
 
Top