/**********************************************************
RunUO 2.0 AoV C# script file
Official Age of Valor Script :: www.uovalor.com
Last modified by 
Filepath: scripts\_custom\items\Craftable artys\baserecipe.cs
Lines of code: 334
***********************************************************/


using System;
using Server;
using Server.Items;
using Server.Gumps;
using Server.Network;
using Server.Menus;
using System.Collections;
using System.Collections.Generic;
using System.IO;





namespace Server.Items
{
	public class BaseRecipe : Item
	{	
			public class ReqSkill
			{
			public double Value;
			public SkillName Skill;
			
				public ReqSkill(SkillName skill,double value)
				{
				Value=value;
				Skill=skill;
				}

				public string Make2String()
				{
				return String.Format("{0}: {1}",Skill,Value);				
				}
				
			}
			
			
			public class ReqRes
			{
			public string name;
			public Type type;
			public int amt;
			
				public ReqRes(string pname,Type ptype,int pamt)
				{
				name=pname;
				type=ptype;
				amt=pamt;
				}
				
				
				public string Make2String()
				{
				return String.Format("{0} {1}",amt,name);				
				}
			}
			
			
		//gm editable fars
		private int m_Uses=5;
		
		[CommandProperty( AccessLevel.GameMaster )]
		public int Uses
		{
			get{ return m_Uses; }
			set{ m_Uses = value; InvalidateProperties(); }
		}		
		
		
		
		//non gm editable vars
				
		public override string DefaultName { get { return String.Format("a recipe scroll for {0}",artyname); } }
		
	
		bool opened=false;		
		public List<ReqSkill> RequiredSkills;
		public List<ReqRes> CommonResources;
		public List<ReqRes> RareResources;
		
		public Item Prototype=null; //a prototype is stored here for displaying stats of item and stuff
	
	
		//per-recipe variables:
		
		public virtual Type CraftedItem { get { return typeof(Item); } }
		public virtual string artyname { get { return "default"; } }
		public virtual double ChanceAtMin{get {return 0.2; }} //% chance to craft if we hit the bare requirements
	
	
	
		public override void GetProperties( ObjectPropertyList list )
		{
			base.GetProperties( list );
			
			GenPrototype();
			
			if ( Uses>0 )list.Add( 1060584, Uses.ToString() ); // uses remaining: ~1_val~
			
			list.Add(1061120); //blank
			Prototype.GetProperties(list);
			
			DelPrototype();
		}		
	
		public static Item GenArty(BaseRecipe rec)
		{
		Item item=null;		
		
			try{ item = Activator.CreateInstance( rec.CraftedItem ) as Item; }
			catch{
			Console.WriteLine("Warning: Recipe {0} [{1}] generating null artifact",rec.Serial,rec.CraftedItem);
			}		
		return item;		
		}
	
	
	
		public void GenPrototype()
		{
			if(Prototype!=null)return;			
			Prototype = GenArty(this);		
		}
		
		public void DelPrototype()
		{
		if(Prototype!=null)Prototype.Delete();
		}
	
	
		public BaseRecipe() : this(5 )
		{
		}
		
		public BaseRecipe(int puses) : base( 10289 )
		{
			Weight = 1.0;
			Uses=puses;			
			InitRequirements();
		}	
		
		public virtual void InitRequirements()
		{
		RequiredSkills = new List<ReqSkill>();		
		RareResources = new List<ReqRes>();				
		CommonResources = new List<ReqRes>();				
		}	
		
		
		public override void OnDoubleClick( Mobile from )
		{
			if (!IsChildOf( from.Backpack ) )return;
					
			if(opened)from.CloseGump(typeof(CraftableArtyGump));
			from.SendGump(new CraftableArtyGump(from,this));
			opened=true;
		}
		
		
		public virtual double GetCraftChance(Mobile from)
		{
		double totalskillreq = 0;
		double totalskillhave = 0;
		double taliscalar=0;
		
			for(int i=0;i<RequiredSkills.Count;i++)
			{
				if(RequiredSkills[i] is ReqSkill)
				{
				ReqSkill rs = RequiredSkills[i] as ReqSkill;
				
					if(from.Skills[rs.Skill].Value<rs.Value)
					{
					return 0;
					}

					
					if ( from.Talisman is BaseTalisman )
					{
						BaseTalisman talisman = (BaseTalisman) from.Talisman;
						
						if ( talisman.Skill == rs.Skill )
						{
							taliscalar+= (talisman.SuccessBonus / (double) 100);
						}
					}				
					
					
				totalskillreq+=rs.Value;					
				totalskillhave+=from.Skills[rs.Skill].Value;
				}			
			}		

		taliscalar/=(double)RequiredSkills.Count;				
		
		double chance = (double)(ChanceAtMin + ((totalskillhave - totalskillreq) / (totalskillreq+(RequiredSkills.Count*50) - totalskillreq) * (1.0 - ChanceAtMin)));
		
		
		if(taliscalar>0)chance*=(1+taliscalar);
		
		
		if(chance<0)chance=0;
		if(chance>1)chance=1;		
		return chance;
		}
		
		
		public virtual bool CheckResources(Mobile from,bool crafting,bool success)
		{		
		
			//check if we have all common resources
		
			for(int i=0;i<CommonResources.Count;i++)
			{
				if(CommonResources[i] is ReqRes)
				{
				ReqRes rs = CommonResources[i] as ReqRes;
				
					if(crafting)
					{
					from.Backpack.ConsumeTotal(rs.type,success? rs.amt : rs.amt/2 );
					}				
					else if(from.Backpack.GetAmount(rs.type)<rs.amt)
					{
					from.SendMessage("You lack enough {0} to craft this!",rs.name);
					return false;
					}
				}
			}		
			
			
			//check if we have all rare resources
			
			for(int i=0;i<RareResources.Count;i++)
			{
				if(RareResources[i] is ReqRes)
				{
				ReqRes rs = RareResources[i] as ReqRes;
				
					if(crafting)
					{
					from.Backpack.ConsumeTotal(rs.type,success? rs.amt : 0.05>Utility.RandomDouble() ? 1 : 0 );
					}				
					else if(from.Backpack.GetAmount(rs.type)<rs.amt)
					{
					from.SendMessage("You lack enough {0} to craft this!",rs.name);
					return false;
					}
				}
			}	
		
		return true;
		}
		
		public bool OnCraft(Mobile from)
		{
		from.CloseGump(typeof(CraftableArtyGump));
		if (!this.IsChildOf( from.Backpack ) )return false;
		opened=false;
		
		
		//check if we have all skillz
		
		for(int i=0;i<RequiredSkills.Count;i++)
		{
			if(RequiredSkills[i] is ReqSkill)
			{
			ReqSkill rs = RequiredSkills[i] as ReqSkill;
			
				if(from.Skills[rs.Skill].Value<rs.Value)
				{
				from.SendMessage("You need at least {0} {1} to craft this item",rs.Value,rs.Skill);
				return false;
				}
			}
		}
	
		
		if(!CheckResources(from,false,false))return false;
		
		
		//if we made it here, then we have the valid requirements to craft it. 
		
			if(GetCraftChance(from)>Utility.RandomDouble())
			{
			//success!
			CheckResources(from,true,true);
			
			
				if(Prototype!=null)
				{
				Item item = GenArty(this);
				
				from.GiveItem(item,false);
				OnAfterCraft(from,item);
				from.SendMessage("You craft the item");				
				
				
					if(Uses>0) //if 0 uses, then its an unlimited use recipe
					{
					Uses--;
						if(Uses<=0)
						{
						from.SendMessage("The recipe scroll is too ruined to use again");
						DelPrototype();
						this.Delete();
						}
					}
				
				return false;
				}
				else
				{
				from.SendMessage("ERROR creating item, contact administrator and keep this scroll.");
				Console.WriteLine("Warning: {0} recipe failed to generate item upon craft",(Item)this);
				return false;
				}		
			
			}
			else
			{
			from.SendMessage("You fail, and some of the resources are lost");
			CheckResources(from,true,false);
			}		
		
		return true;
		}
		
		
		public virtual void OnAfterCraft(Mobile from,Item item)
		{		
		}
		
		
		public void OnCancel(Mobile from)
		{
		opened=false;
		from.SendMessage("You decide not to craft the item");
		}
		
		public override void OnDelete()
		{
		DelPrototype();
		base.OnDelete();
		}		


		public BaseRecipe( Serial serial ) : base( serial )
		{
		}

		public override void Serialize( GenericWriter writer )
		{
			base.Serialize( writer );
			writer.Write( (int) 1 ); // version
			
			writer.Write(m_Uses);
		}

		public override void Deserialize( GenericReader reader )
		{
			base.Deserialize( reader );
			int version = reader.ReadInt();
			
			if(version>=1)m_Uses=reader.ReadInt();
			
			
			//always last
			InitRequirements();
		}
	}
}




namespace Server.Gumps
{


	public class CraftableArtyGump : Gump
	{
	Mobile m_from;
	BaseRecipe m_recipe;
	
	static int spacing=20;					

		public CraftableArtyGump(Mobile from, BaseRecipe recipe)	: base( 40, 40 )
		{
			m_from=from;
			m_recipe=recipe;		
			
			int maxcount=m_recipe.RequiredSkills.Count;
			if(m_recipe.RareResources.Count>maxcount)maxcount=m_recipe.RareResources.Count;
			if(m_recipe.CommonResources.Count>maxcount)maxcount=m_recipe.CommonResources.Count;
			
		
			this.Closable=true;
			this.Disposable=true;
			this.Dragable=true;
			this.Resizable=false;
			this.AddPage(0);
			this.AddBackground(70, 49, 650, 234+(spacing*maxcount), 9300);			
		
			if(recipe.Prototype!=null)	this.AddItem( 85, 76, recipe.Prototype.ItemID,recipe.Prototype.Hue );
			else recipe.GenPrototype();			
			recipe.DelPrototype();
			
			this.AddLabel(226, 75, 0, @m_recipe.artyname);
			
			this.AddLabel(494, 75, 0, String.Format("Your success Chance: {0}%",Math.Round(m_recipe.GetCraftChance(from)*100,2)));
			
			this.AddLabel(92, 169, 0, @"Skill Requirements");
			this.AddLabel(251, 169, 0, @"Regular Resource Requirements");
			this.AddLabel(494, 169, 0, @"Rare Resource Requirements");
			this.AddImageTiled(115, 188, 552, 13, 58);
			this.AddLabel(94, 117, 0, @"This is a recipe scroll which will allow you to craft a special item if you meet the following");
			this.AddLabel(94, 137, 0, @"requirements.  The rare resources are not as likely to be lost if you fail.");
			this.AddImage(85, 188, 57);
			this.AddImage(667, 188, 59);
			this.AddImageTiled(115, 58, 552, 13, 58);
			this.AddImage(85, 58, 57);
			this.AddImage(667, 58, 59);
			
			for(int i=0;i<maxcount;i++)
			{
			if(m_recipe.RequiredSkills.Count>i)	this.AddLabel(92,210+(spacing*i), 0, @m_recipe.RequiredSkills[i].Make2String());
			if(m_recipe.CommonResources.Count>i)	this.AddLabel(251,210+(spacing*i), 0, @m_recipe.CommonResources[i].Make2String());
			if(m_recipe.RareResources.Count>i)	this.AddLabel(494,210+(spacing*i), 0, @m_recipe.RareResources[i].Make2String());			
			}			
			
			
			this.AddImageTiled(115, 219+(spacing*maxcount), 552, 13, 58);
			this.AddImage(667, 219+(spacing*maxcount), 59);
			this.AddImage(85, 219+(spacing*maxcount), 57);
			this.AddButton(313, 242+(spacing*maxcount), 247, 248, (int)Buttons.ok, GumpButtonType.Reply, 0);
			this.AddButton(405, 242+(spacing*maxcount), 242, 241, (int)Buttons.cancel, GumpButtonType.Reply, 0);
			this.AddImage(54, 23, 10600);
			this.AddImage(49, 278+(spacing*maxcount), 10600);
			this.AddImage(662, 23, 10602);
			this.AddImageTiled(124, 24, 594, 29, 10601);
			this.AddImageTiled(88, 278+(spacing*maxcount), 603, 29, 10601);
			this.AddImage(661, 278+(spacing*maxcount), 10602);

		}
		
		public enum Buttons
		{
			TextEntry1,
			ok,
			cancel
		}
		
		public override void OnResponse( NetState state, RelayInfo info )
		{
			if ( info.ButtonID == (int)Buttons.ok )
			{
			m_recipe.OnCraft(m_from);
			}
			else
			{
			m_recipe.OnCancel(m_from);
			}

		}		
		

	}





}



