context: using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Linq;
  
  using Server;
  using Server.Mobiles;
  using Server.Items;
  using Server.ContextMenus;
  using Server.Targeting;
  using Server.Regions;
  using Server.Engines.BuffIcons;
  
  namespace Server.Engines.Quests
  {
  	public class QuestHelper
  	{
  		public static void RemoveAcceleratedSkillgain( PlayerMobile from )
  		{
  			Region region = from.Region;
  
  			while ( region != null )
  			{
  				if ( region is ApprenticeRegion && ( (ApprenticeRegion) region ).Table[from] is BuffInfo )
  				{
  					BuffInfo.RemoveBuff( from, (BuffInfo) ( (ApprenticeRegion) region ).Table[from] );
  					( (ApprenticeRegion) region ).Table[from] = null;
  				}
  
  				region = region.Parent;
  			}
  		}
  
  		public static BaseQuest RandomQuest( PlayerMobile from, Type[] quests, object quester )
  		{
  			if ( quests == null || ( quests != null && quests.Length == 0 ) )
  				return null;
  
  			// give it 10 tries to generate quest
  			for ( int i = 0; i < 10; i++ )
  			{
  				BaseQuest quest = Construct( quests[Utility.Random( quests.Length )] ) as BaseQuest;
  
  				if ( quest != null )
  				{
  					quest.Owner = from;
  					quest.Quester = quester;
  
  					if ( CanOffer( from, quest, quests.Length == 1 ) )
  						return quest;
  					else if ( quest.StartingMobile != null && !quest.DoneOnce && quests.Length == 1 )
  						quest.StartingMobile.OnOfferFailed();
  				}
  
  				if ( quests.Length == 1 )
  					return null;
  			}
  
  			return null;
  		}
  
  		public static bool CanOffer( PlayerMobile from, BaseQuest quest, bool message )
  		{
  			if ( !quest.CanOffer() )
  				return false;
  
  			// if a player wants to start quest chain (already started) again (not osi)			
  			if ( quest.ChainID != QuestChain.None && FirstChainQuest( quest, quest.Quester ) && from.Chains.ContainsKey( quest.ChainID ) )
  				return false;
  
  			if ( !Delayed( from, quest, message ) )
  				return false;
  
  			for ( int i = quest.Objectives.Count - 1; i >= 0; i-- )
  			{
  				Type type = quest.Objectives[i].Type();
  
  				if ( type == null )
  					continue;
  
  				for ( int j = from.Quests.Count - 1; j >= 0; j-- )
  				{
  					BaseQuest pQuest = from.Quests[j];
  
  					for ( int k = pQuest.Objectives.Count - 1; k >= 0; k-- )
  					{
  						BaseObjective obj = pQuest.Objectives[k];
  
  						if ( type == obj.Type() )
  							return false;
  					}
  				}
  			}
  
  			return true;
  		}
  
  		public static bool Delayed( PlayerMobile player, BaseQuest quest, bool message )
  		{
  			List<QuestRestartInfo> doneQuests = player.DoneQuests;
  
  			for ( int i = doneQuests.Count - 1; i >= 0; i-- )
  			{
  				QuestRestartInfo restartInfo = doneQuests[i];
  
  				if ( restartInfo.QuestType == quest.GetType() )
  				{
  					if ( quest.DoneOnce )
  					{
  						if ( message && quest.StartingMobile != null )
  							quest.StartingMobile.Say( 1075454 ); // I can not offer you the quest again.
  
  						return false;
  					}
  
  					DateTime endTime = restartInfo.RestartTime;
  
  					if ( DateTime.Now < endTime )
  						return false;
  
  					if ( quest.RestartDelay > TimeSpan.Zero )
  						doneQuests.RemoveAt( i );
  
  					return true;
  				}
  			}
  
  			return true;
  		}
  
  		public static void Delay( PlayerMobile player, Type type, TimeSpan delay )
  		{
  			for ( int i = 0; i < player.DoneQuests.Count; i++ )
  			{
  				QuestRestartInfo restartInfo = player.DoneQuests[i];
  
  				if ( restartInfo.QuestType == type )
  				{
  					restartInfo.Reset( delay );
  					return;
  				}
  			}
  
  			player.DoneQuests.Add( new QuestRestartInfo( type, delay ) );
  		}
  
  		public static bool InProgress( PlayerMobile player, Type[] quests )
  		{
  			if ( quests == null )
  				return false;
  
  			for ( int i = 0; i < quests.Length; i++ )
  			{
  				for ( int j = 0; j < player.Quests.Count; j++ )
  				{
  					BaseQuest quest = player.Quests[j];
  
  					if ( quests[i].IsAssignableFrom( quest.GetType() ) )
  					{
  						player.CloseGump( typeof( BaseQuestGump ) );
  
  						if ( quest.Completed )
  						{
  							player.SendGump( new MLQuestFinishGump( player, quest ) );
  						}
  						else
  						{
  							player.SendGump( new MLQuestConversationGump( quest, MLQuestConverType.InProgress ) );
  							quest.InProgress();
  						}
  
  						return true;
  					}
  				}
  			}
  			return false;
  		}
  
  		public static bool InProgress( PlayerMobile player, MondainQuester quester )
  		{
  			for ( int i = 0; i < player.Quests.Count; i++ )
  			{
  				BaseQuest quest = player.Quests[i];
  
  				if ( quest.Quester == null )
  					continue;
  
  				if ( quest.Quester.GetType() == quester.GetType() )
  				{
  					player.CloseGump( typeof( BaseQuestGump ) );
  
  					if ( quest.Completed )
  					{
  						if ( quest.Complete == null && !AnyRewards( quest ) )
  						{
  							quest.GiveRewards();
  						}
  						else
  						{
  							player.SendGump( new MLQuestFinishGump( player, quest ) );
  						}
  					}
  					else
  					{
  						player.SendGump( new MLQuestConversationGump( quest, MLQuestConverType.InProgress ) );
  						quest.InProgress();
  					}
  
  					return true;
  				}
  			}
  
  			return false;
  		}
  
  		public static bool AnyRewards( BaseQuest quest )
  		{
  			for ( int i = 0; i < quest.Rewards.Count; i++ )
  			{
  				BaseReward reward = quest.Rewards[i];
  
  				if ( reward.Type != null )
  					return true;
  			}
  
  			return false;
  		}
  
  		public static bool DeliveryArrived( PlayerMobile player, BaseVendor vendor )
  		{
  			for ( int i = 0; i < player.Quests.Count; i++ )
  			{
  				BaseQuest quest = player.Quests[i];
  
  				for ( int j = 0; j < quest.Objectives.Count; j++ )
  				{
  					BaseObjective objective = quest.Objectives[j];
  
  					if ( objective is DeliverObjective )
  					{
  						DeliverObjective deliver = (DeliverObjective) objective;
  
  						if ( deliver.Update( vendor ) )
  						{
  							if ( quest.Completed )
  							{
  								player.SendLocalizedMessage( 1046258, null, 0x23 ); // Your quest is complete.												
  								player.PlaySound( quest.CompleteSound );
  
  								quest.OnCompleted();
  
  								player.CloseGump( typeof( BaseQuestGump ) );
  
  								if ( vendor is MondainQuester )
  									player.SendGump( new MLQuestFinishGump( player, quest, (MondainQuester) vendor ) );
  								else
  									player.SendGump( new MLQuestFinishGump( player, quest ) );
  							}
  
  							return true;
  						}
  					}
  				}
  			}
  
  			return false;
  		}
  
  		public static bool QuestLimitReached( PlayerMobile player )
  		{
  			if ( player.Quests.Count >= 10 )
  			{
  				player.SendLocalizedMessage( 1075141 ); // You are too busy with other tasks at this time.
  				return true;
  			}
  
  			return false;
  		}
  
  		public static bool FirstChainQuest( BaseQuest quest, object quester )
  		{
  			Type[] quests = null;
  
  			if ( quester is MondainQuester )
  			{
  				MondainQuester mQuester = (MondainQuester) quester;
  
  				quests = mQuester.Quests;
  			}
  			else if ( quester is BaseQuestItem )
  			{
  				BaseQuestItem iQuester = (BaseQuestItem) quester;
  
  				quests = iQuester.Quests;
  			}
  
  			if ( quests != null )
  			{
  				for ( int i = 0; i < quests.Length; i++ )
  				{
  					if ( quests[i] == quest.GetType() )
  						return true;
  				}
  			}
  
  			return false;
  		}
  
  		public static Type FindFirstChainQuest( BaseQuest quest )
  		{
  			if ( quest == null )
  				return null;
  
  			Type[] quests = null;
  
  			if ( quest.Quester is MondainQuester )
  			{
  				MondainQuester mQuester = (MondainQuester) quest.Quester;
  
  				quests = mQuester.Quests;
  			}
  			else if ( quest.Quester is BaseQuestItem )
  			{
  				BaseQuestItem iQuester = (BaseQuestItem) quest.Quester;
  
  				quests = iQuester.Quests;
  			}
  
  			if ( quests != null )
  			{
  				for ( int i = 0; i < quests.Length; i++ )
  				{
  					BaseQuest fQuest = Construct( quests[i] ) as BaseQuest;
  
  					if ( fQuest != null && fQuest.ChainID == quest.ChainID )
  						return fQuest.GetType();
  				}
  			}
  
  			return null;
  		}
  
  		public static Region FindRegion( string name )
  		{
  			if ( name == null )
  				return null;
  
  			Region reg = null;
  
  			if ( Map.Trammel.Regions.TryGetValue( name, out reg ) )
  				return reg;
  
  			if ( Map.Felucca.Regions.TryGetValue( name, out reg ) )
  				return reg;
  
  			if ( Map.Ilshenar.Regions.TryGetValue( name, out reg ) )
  				return reg;
  
  			if ( Map.Malas.Regions.TryGetValue( name, out reg ) )
  				return reg;
  
  			if ( Map.Tokuno.Regions.TryGetValue( name, out reg ) )
  				return reg;
  
  			if ( Map.TerMur.Regions.TryGetValue( name, out reg ) )
  				return reg;
  
  			return reg;
  		}
  
  		public static void CompleteQuest( PlayerMobile from, BaseQuest quest )
  		{
  			if ( quest == null )
  				return;
  
  			for ( int i = 0; i < quest.Objectives.Count; i++ )
  			{
  				BaseObjective obj = quest.Objectives[i];
  
  				obj.Complete();
  			}
  
  			from.SendLocalizedMessage( 1046258, null, 0x23 ); // Your quest is complete.							
  			from.CloseGump( typeof( BaseQuestGump ) );
  			from.SendGump( new MLQuestFinishGump( from, quest ) );
  			from.PlaySound( quest.CompleteSound );
  
  			quest.OnCompleted();
  		}
  
  		public static void DeleteItems( PlayerMobile from, Type itemType, int amount, bool questItem )
  		{
  			if ( from.Backpack == null || itemType == null || amount <= 0 )
  				return;
  
  			Item[] items = from.Backpack.FindItemsByType( itemType );
  
  			int deleted = 0;
  
  			for ( int i = items.Length - 1; i >= 0 && deleted < amount; i-- )
  			{
  				Item item = items[i];
  
  				if ( item.QuestItem || !questItem )
  				{
  					item.QuestItem = false;
  
  					if ( deleted + item.Amount > amount )
  					{
  						item.Amount -= amount - deleted;
  						deleted += amount - deleted;
  					}
  					else
  					{
  						item.Delete();
  						deleted += item.Amount;
  					}
  				}
  			}
  
  			if ( deleted < amount )
  			{
  				foreach ( var item in from.GetEquippedItems() )
  				{
  					if ( deleted >= amount )
  						break;
  
  					if ( item.QuestItem || !questItem )
  					{
  						if ( itemType.IsAssignableFrom( item.GetType() ) )
  						{
  							deleted += item.Amount;
  
  							item.Delete();
  						}
  					}
  				}
  			}
  		}
  
  		public static void DeleteItems( BaseQuest quest )
  		{
  			for ( int i = 0; i < quest.Objectives.Count; i++ )
  			{
  				BaseObjective objective = quest.Objectives[i];
  
  				DeleteItems( quest.Owner, objective.Type(), objective.MaxProgress, true );
  				RemoveStatus( quest.Owner, objective.Type() );
  			}
  		}
  
  		public static bool TryDeleteItems( BaseQuest quest )
  		{
  			if ( quest == null )
  				return false;
  
  			for ( int i = 0; i < quest.Objectives.Count; i++ )
  			{
  				if ( quest.Objectives[i] is ObtainObjective )
  				{
  					ObtainObjective obtain = (ObtainObjective) quest.Objectives[i];
  
  					if ( obtain.MaxProgress > CountQuestItems( quest.Owner, obtain.Obtain ) )
  						return false;
  				}
  				else if ( quest.Objectives[i] is DeliverObjective )
  				{
  					DeliverObjective deliver = (DeliverObjective) quest.Objectives[i];
  
  					if ( quest.StartingItem != null )
  						continue;
  					else if ( deliver.MaxProgress > CountQuestItems( quest.Owner, deliver.Delivery ) )
  					{
  						quest.Owner.SendLocalizedMessage( 1074813 );  // You have failed to complete your delivery.
  						deliver.Fail();
  
  						return false;
  					}
  				}
  			}
  
  			DeleteItems( quest );
  
  			return true;
  		}
  
  		public static int CountQuestItems( PlayerMobile from, Type type )
  		{
  			int count = 0;
  
  			if ( from.Backpack == null )
  				return count;
  
  			Item[] items = from.Backpack.FindItemsByType( type );
  
  			for ( int i = 0; i < items.Length; i++ )
  			{
  				Item item = items[i];
  
  				if ( item.QuestItem )
  					count += item.Amount;
  			}
  
  			return count;
  		}
  
  		public static int RemoveStatus( PlayerMobile from, Type type )
  		{
  			if ( type == null )
  				return 0;
  
  			Item[] items = from.Backpack.FindItemsByType( type );
  
  			int count = 0;
  
  			for ( int i = 0; i < items.Length; i++ )
  			{
  				Item item = items[i];
  
  				if ( item.QuestItem )
  				{
  					count += 1;
  					item.QuestItem = false;
  				}
  			}
  
  			return count;
  		}
  
  		public static void RemoveStatus( PlayerMobile from, Item item )
  		{
  			for ( int i = from.Quests.Count - 1; i >= 0; i-- )
  			{
  				BaseQuest quest = from.Quests[i];
  
  				for ( int j = quest.Objectives.Count - 1; j >= 0; j-- )
  				{
  					if ( quest.Objectives[j] is ObtainObjective )
  					{
  						ObtainObjective obtain = (ObtainObjective) quest.Objectives[j];
  
  						if ( obtain.Obtain != null && obtain.Obtain.IsAssignableFrom( item.GetType() ) )
  						{
  							obtain.CurProgress -= item.Amount;
  							item.QuestItem = false;
  							from.SendLocalizedMessage( 1074769 ); // An item must be in your backpack (and not in a container within) to be toggled as a quest item. 	
  							return;
  						}
  					}
  					else if ( quest.Objectives[j] is DeliverObjective )
  					{
  						DeliverObjective deliver = (DeliverObjective) quest.Objectives[j];
  
  						if ( deliver.Delivery != null && deliver.Delivery.IsAssignableFrom( item.GetType() ) )
  						{
  							from.SendLocalizedMessage( 1074813 );  // You have failed to complete your delivery.							
  							DeleteItems( from, deliver.Delivery, deliver.MaxProgress, false );
  							deliver.Fail();
  							item.Delete();
  							return;
  						}
  					}
  				}
  			}
  		}
  
  		public static bool CheckCreature( PlayerMobile player, BaseCreature creature )
  		{
  			for ( int i = player.Quests.Count - 1; i >= 0; i-- )
  			{
  				BaseQuest quest = player.Quests[i];
  
  				for ( int j = quest.Objectives.Count - 1; j >= 0; j-- )
  				{
  					if ( quest.Objectives[j] is SlayObjective )
  					{
  						SlayObjective slay = (SlayObjective) quest.Objectives[j];
  
  						if ( slay.Update( creature ) )
  						{
  							if ( quest.Completed )
  								quest.OnCompleted();
  							if ( slay.Completed )
  								player.PlaySound( quest.UpdateSound );
  
  							return true;
  						}
  					}
  				}
  			}
  
  			return false;
  		}
  
  		public static bool CheckItem( PlayerMobile player, Item item )
  		{
  			for ( int i = player.Quests.Count - 1; i >= 0; i-- )
  			{
  				BaseQuest quest = player.Quests[i];
  
  				for ( int j = quest.Objectives.Count - 1; j >= 0; j-- )
  				{
  					BaseObjective objective = quest.Objectives[j];
  
  					if ( objective is ObtainObjective )
  					{
  						ObtainObjective obtain = (ObtainObjective) objective;
  
  						if ( obtain.Update( item ) )
  						{
  							if ( quest.Completed )
  								quest.OnCompleted();
  							if ( obtain.Completed )
  								player.PlaySound( quest.UpdateSound );
  
  							return true;
  						}
  					}
  				}
  			}
  
  			return false;
  		}
  
  		public static bool CheckSkill( PlayerMobile player, Skill skill )
  		{
  			for ( int i = player.Quests.Count - 1; i >= 0; i-- )
  			{
  				BaseQuest quest = player.Quests[i];
  
  				for ( int j = quest.Objectives.Count - 1; j >= 0; j-- )
  				{
  					BaseObjective objective = quest.Objectives[j];
  
  					if ( objective is ApprenticeObjective )
  					{
  						ApprenticeObjective apprentice = (ApprenticeObjective) objective;
  
  						if ( apprentice.Update( skill ) )
  						{
  							if ( quest.Completed )
  								quest.OnCompleted();
  							if ( apprentice.Completed )
  								player.PlaySound( quest.UpdateSound );
  						}
  					}
  				}
  			}
  
  			return false;
  		}
  
  		public static bool EnhancedSkill( PlayerMobile player, Skill skill )
  		{
  			if ( player == null || player.Region == null || skill == null )
  				return false;
  
  			for ( int i = player.Quests.Count - 1; i >= 0; i-- )
  			{
  				BaseQuest quest = player.Quests[i];
  
  				for ( int j = quest.Objectives.Count - 1; j >= 0; j-- )
  				{
  					BaseObjective objective = quest.Objectives[j];
  
  					if ( objective is ApprenticeObjective && !objective.Completed )
  					{
  						ApprenticeObjective apprentice = (ApprenticeObjective) objective;
  
  						if ( apprentice.Region != null )
  						{
  							if ( player.Region.IsPartOf( apprentice.Region ) && skill.SkillName == apprentice.Skill )
  								return true;
  						}
  					}
  				}
  			}
  
  			return false;
  		}
  
  		public static bool OnDiscorded( PlayerMobile player, Mobile target )
  		{
  			for ( int i = player.Quests.Count - 1; i >= 0; i-- )
  			{
  
gt: 				BaseQuest quest = player.Quests[i];