context: //--- Aura Script -----------------------------------------------------------
  // Malcolm
  //--- Description -----------------------------------------------------------
  // General store manager
  //---------------------------------------------------------------------------
  
  public class MalcolmScript : NpcScript
  {
  	public override void Load()
  	{
  		SetRace(10002);
  		SetName("_malcolm");
  		SetBody(height: 1.22f);
  		SetFace(skinColor: 16, eyeType: 26, eyeColor: 162);
  		SetStand("human/male/anim/male_natural_stand_npc_malcolm_retake", "human/male/anim/male_natural_stand_npc_malcolm_talk");
  		SetLocation(8, 1238, 1655, 59);
  		SetGiftWeights(beauty: 2, individuality: -1, luxury: 0, toughness: 0, utility: 1, rarity: 2, meaning: 0, adult: 0, maniac: 0, anime: 0, sexy: 0);
  
  		EquipItem(Pocket.Face, 4900, 0x00FFB859, 0x003C6274, 0x00505968);
  		EquipItem(Pocket.Hair, 4155, 0x00ECBC58, 0x00ECBC58, 0x00ECBC58);
  		EquipItem(Pocket.Armor, 15655, 0x00D8C9B7, 0x00112A13, 0x00131313);
  		EquipItem(Pocket.Shoe, 17287, 0x00544838, 0x00000000, 0x00000000);
  		EquipItem(Pocket.RightHand1, 40491, 0x00808080, 0x00000000, 0x00000000);
  		EquipItem(Pocket.LeftHand1, 40017, 0x003F7246, 0x00C0B584, 0x003F4B40);
  
  		AddPhrase("Maybe I should wrap it up and call it a day... (confused)");
  		AddPhrase("Aww! My legs hurt. My feet are all swollen from standing all day long.");
  		AddPhrase("I wonder what Nora is doing now...");
  		AddPhrase("These travelers will buy something sooner or later.");
  		AddPhrase("So much work, so little time... I'm in trouble!");
  		AddPhrase("Dear love, you live right next door, yet I cannot see you... I can't sleep at night thinking of you...");
  		AddPhrase("Ha ha, look at what that person is wearing. (laugh)");
  		AddPhrase("It isn't easy running a shop alone... Maybe I should hire a clerk.");
  	}
  
  	protected override async Task Talk()
  	{
  		await Intro(L("While his thin face makes him look weak,<br/>and his soft and delicate hands seem much too feminine,<br/>his cool long blonde hair gives him a suave look.<br/>He looks like he just came out of a workshop since he's wearing a heavy leather apron."));
  
  		Msg("What can I do for you?", Button("Start a Conversation", "@talk"), Button("Shop", "@shop"), Button("Repair Item", "@repair"));
  
  		switch (await Select())
  		{
  			case "@talk":
  				Greet();
  				Msg(Hide.Name, GetMoodString(), FavorExpression());
  
  				var today = ErinnTime.Now.ToString("yyyyMMdd");
  				if (today != Player.Vars.Perm["malcolm_title_gift"])
  				{
  					string message1 = null;
  					string message2 = null;
  
  					switch (Player.Title)
  					{
  						case 10059: // is a friend of Trefor
  							message2 = L("I am an old friend of Trefor.<br/>So please receive my small token of appreciation.");
  							break;
  
  						case 10061: // is a friend of Malcolm
  							message2 = L("Welcome, <username/>!<br/>How could I forget my old pal?<br/>You are always my VIP, <username/>.");
  							break;
  
  						case 10062: // is a friend of Nora
  							message1 = L("Oh, you are friends with Nora. You know what?<br/>A friend of Nora is a friend of mine.");
  							message2 = L("This is my small token of appreciation<br/>for your kindness to Nora.");
  							break;
  					}
  
  					if (message1 != null || message2 != null)
  					{
  						if (message1 != null)
  							Msg(message1);
  
  						Player.Vars.Perm["malcolm_title_gift"] = today;
  
  						Player.GiveItem(61001); // Score Scroll
  						Player.Notice(L("Received Score Scroll from Malcolm."));
  						Player.SystemMsg(L("Received Score Scroll from Malcolm."));
  
  						if (message2 != null)
  							Msg(message2);
  					}
  				}
  
  				if (Player.IsUsingTitle(11001))
  				{
  					Msg("...");
  					Msg("...*Sigh*");
  					Msg("Has your life gotten any better after saving the Goddess?");
  				}
  				else if (Player.IsUsingTitle(11002))
  				{
  					Msg("You're the... Guardian of Erinn?<br/>I don't know what you do exactly,<br/>but you seem to leave<br/>a really good impression on people.");
  					Msg("...I'm a bit jealous...");
  				}
  
  				await Conversation();
  				break;
  
  			case "@shop":
  				Msg("Welcome to <npcname/>'s General Shop.<br/>Look around as much as you wish. Clothes, accessories and other goods are in stock.");
  				OpenShop("MalcolmShop");
  				return;
  
  			case "@repair":
  				Msg("What item do you want to repair?<br/>You can repair various items such as Music Instruments and Glasses.<repair rate='95' stringid='(*/misc_repairable/*)|(*/pouch/bag/*)' />");
  
  				while (true)
  				{
  					var repair = await Select();
  
  					if (!repair.StartsWith("@repair"))
  						break;
  
  					var result = Repair(repair, 95, "/misc_repairable/", "/pouch/bag/");
  					if (!result.HadGold)
  					{
  						RndMsg(
  							"Sorry, you need more money.",
  							"I'm sorry but you don't have enough money.",
  							"Um... OK.<br/>If you don't have enough money at the moment, why don't you come back later?"
  						);
  					}
  					else if (result.Points == 1)
  					{
  						if (result.Fails == 0)
  							RndMsg(
  								"I'm happy to say it's repaired.",
  								"OK, 1 point repair is finished.",
  								"It has been repaired well."
  							);
  						else
  							RndMsg(
  								"Oh no! I'm so sorry.",
  								"Aw... I'm terribly sorry."
  							);
  					}
  					else if (result.Points > 1)
  					{
  						if (result.Fails == 0)
  							RndMsg(
  								"The repairing is complete.",
  								"Hahaha, it's perfectly repaired.",
  								"Wow! It has been repaired perfectly.<br/>Yes, I'm surprised, too."
  							);
  						else
  							// TODO: Use string format once we have XML dialogues.
  							Msg(result.Successes + " point(s) repaired.<br/>Unfortunately, I have failed in repairing " + result.Fails + " point(s).");
  					}
  				}
  
  				Msg("Let me give you a tip.<br/>If you bless your item with Holy Water of Lymilark,<br/>you can reduce abrasion which means<br/>your item will wear off more slowly over time.<repair hide='true'/>");
  				break;
  		}
  
  		End("Goodbye, <npcname/>. I'll see you later!");
  	}
  
  	private void Greet()
  	{
  		if (Player.IsDoingPtjFor(NPC))
  		{
  			Msg(FavorExpression(), L("How are you doing on your work?<br/>Please keep up the good work."));
  		}
  		else if (Memory <= 0)
  		{
  			Msg(FavorExpression(), L("Welcome to the General Shop. This must be your first visit here."));
  		}
  		else if (Memory == 1)
  		{
  			Msg(FavorExpression(), L("Thank you for coming again."));
  		}
  		else if (Memory == 2)
  		{
  			Msg(FavorExpression(), L("Welcome, <username/>."));
  		}
  		else if (Memory <= 6)
  		{
  			Msg(FavorExpression(), L("Thank you for visiting again, <username/>.<br/>If you come and shop here regularly,<br/>I will treat you as a VIP customer. Ha ha."));
  		}
  		else
  		{
  			Msg(FavorExpression(), L("Ah, my VIP customer, <username/>! Welcome."));
  		}
  
  		UpdateRelationAfterGreet();
  	}
  
  	protected override async Task Keywords(string keyword)
  	{
  		switch (keyword)
  		{
  			case "personal_info":
  				if (Memory >= 15 && Favor >= 50 && Stress <= 5)
  				{
  					Msg(FavorExpression(), "I think you know this already, <username/>, but anyway, I'm in love with Nora.<br/>The problem is, she doesn't acknowledge my feelings for her<br/>and treats all those travelers with so much kindness that I become really jealous.<br/>I try to understand that it's a part of her job but I can't help feeling what I feel.");
  					Msg("Can you understand the pain I am feeling?");
  					ModifyRelation(Random(2), 0, Random(2));
  				}
  				else if (Memory >= 15 && Favor >= 30 && Stress <= 5)
  				{
  					Msg(FavorExpression(), "I have an older brother who's away on a journey.<br/>I haven't heard from him for a long time and I miss him a lot.<br/>He was always very nice to me...");
  					ModifyRelation(Random(2), 0, Random(2));
  				}
  				else if (Favor >= 10 && Stress <= 10)
  				{
  					Msg(FavorExpression(), "These days, there are so many people that all the goods are nearly sold out.<br/>I'm making as many as I can to keep up the stock but there is a limit to what I can make alone.<br/>And since I can't afford to hire someone... I ask you for your understanding on any shortages we may have.");
  					ModifyRelation(Random(2), Random(2), Random(2));
  				}
  				else if (Favor <= -10)
  				{
  					Msg(FavorExpression(), "You're poking your nose into my business.");
  					ModifyRelation(Random(2), 0, Random(1, 3));
  				}
  				else if (Favor <= -30 && Stress <= 10)
  				{
  					Msg(FavorExpression(), "Why do you keep asking these questions? Stop it.");
  					ModifyRelation(Random(2), 0, Random(1, 3));
  				}
  				else if (Favor <= -30 && Stress > 10)
  				{
  					Msg(FavorExpression(), "You like meddling in other people's business, don't you? It won't do you any good.");
  
gt: 					ModifyRelation(Random(2), -Random(2), Random(1, 4));