Files
Unstable Kitsune b918192e4e Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
2023-11-28 23:20:26 -05:00

1562 lines
41 KiB
C#

using System;
using Server;
using Server.Gumps;
using Server.Network;
using Server.Mobiles;
using System.IO;
using System.Globalization;
using System.Collections.Generic;
using Server.Targeting;
using Server.Engines.PartySystem;
using System.Data;
using System.Xml;
using Server.Engines.XmlSpawner2;
namespace Server.Items
{
public interface IXmlQuest
{
string Name { get; set; }
string NoteString { get; set; }
string TitleString { get; set; }
string Objective1 { get; set; }
string Objective2 { get; set; }
string Objective3 { get; set; }
string Objective4 { get; set; }
string Objective5 { get; set; }
string Description1 { get; set; }
string Description2 { get; set; }
string Description3 { get; set; }
string Description4 { get; set; }
string Description5 { get; set; }
bool Completed1 { get; set; }
bool Completed2 { get; set; }
bool Completed3 { get; set; }
bool Completed4 { get; set; }
bool Completed5 { get; set; }
string State1 { get; set; }
string State2 { get; set; }
string State3 { get; set; }
string State4 { get; set; }
string State5 { get; set; }
bool PlayerMade { get; set; }
bool PartyEnabled { get; set; }
int PartyRange { get; set; }
int Difficulty { get; set; }
PlayerMobile Owner { get; set; }
PlayerMobile Creator { get; set; }
Container ReturnContainer { get; set; }
Item RewardItem { get; set; }
XmlAttachment RewardAttachment { get; set; }
string Status { get; set; }
string ExpirationString { get; }
bool CanSeeReward { get; set; }
bool AutoReward { get; set; }
bool Repeatable { get; set; }
bool IsValid { get; }
bool AlreadyDone { get; }
bool IsCompleted { get; }
bool Deleted { get; }
Container Pack { get; }
bool HandlesOnSkillUse { get; }
double Expiration { get; set; }
DateTime TimeCreated { get; set; }
void CheckAutoReward();
void CheckRewardItem();
void Invalidate();
void OnSkillUse(Mobile m, Skill skill, bool success);
List<XmlQuest.JournalEntry> Journal { get; set; }
string AddJournalEntry { set;}
}
public interface ITemporaryQuestAttachment
{
Mobile QuestOwner { get; set; }
}
public abstract class XmlQuest
{
public static void Initialize()
{
EventSink.OnKilledBy += OnKilledBy;
}
public const PlayerFlag CarriedXmlQuestFlag = (PlayerFlag)0x00100000;
public const bool QuestPointsEnabled = true;
public class JournalEntry
{
private string m_EntryID;
private string m_EntryText;
public string EntryID { get { return m_EntryID; } set { m_EntryID = value; } }
public string EntryText { get { return m_EntryText; } set { m_EntryText = value; } }
public JournalEntry(string ID, string text)
{
EntryID = ID;
EntryText = text;
}
}
public class GetCollectTarget : Target
{
IXmlQuest m_quest;
public GetCollectTarget(IXmlQuest quest)
: base(30, false, TargetFlags.None)
{
m_quest = quest;
}
protected override void OnTarget(Mobile from, object targeted)
{
if (targeted is Item && m_quest != null && !m_quest.Deleted)
{
XmlQuest.Collect(from, (Item)targeted, m_quest);
from.CloseGump(typeof(XmlQuestStatusGump));
from.SendGump(new XmlQuestStatusGump(m_quest, m_quest.TitleString));
}
}
}
public static void QuestButton(QuestGumpRequestArgs e)
{
if (e == null || e.Mobile == null) return;
Mobile from = e.Mobile;
from.CloseGump(typeof(XMLQuestLogGump));
// bring up the quest status gump
from.SendGump(new XMLQuestLogGump(from));
// bring up the normal quest objectives gump
//NormalQuestButton(from as PlayerMobile);
}
public static void QuestButton(NetState state, IEntity e, EncodedReader reader)
{
if (state == null || state.Mobile == null) return;
Mobile from = state.Mobile;
from.CloseGump(typeof(XMLQuestLogGump));
// bring up the quest status gump
from.SendGump(new XMLQuestLogGump(from));
// bring up the normal quest objectives gump
//NormalQuestButton(from as PlayerMobile);
}
// this just brings up the normal quest objectives gump
public static void NormalQuestButton(PlayerMobile from)
{
if (from == null || from.Quest == null) return;
from.Quest.ShowQuestLog();
}
public static void RemoveTemporaryQuestObjects(Mobile questowner, string questname)
{
// find all TemporaryQuestObject attachments associated with the owner with the given name, and delete them
List<XmlAttachment> list = new List<XmlAttachment>();
foreach (XmlAttachment i in XmlAttach.Values)
{
// check for type
if (i != null && !i.Deleted && i is ITemporaryQuestAttachment && ((ITemporaryQuestAttachment)i).QuestOwner == questowner && i.Name == questname)
{
list.Add(i);
}
}
foreach (XmlAttachment i in list)
{
i.Delete();
}
}
private static void ReturnCollected(IXmlQuest quest, Item item)
{
if (item == null) return;
// if this was player made, then return the item to the creator
// dont allow players to return items to themselves. This prevents possible exploits where quests are used as
// item transporters
if (quest != null && quest.PlayerMade && (quest.Creator != null) && !quest.Creator.Deleted && (quest.Creator != quest.Owner) && !item.QuestItem)
{
bool returned = false;
if ((quest.ReturnContainer != null) && !quest.ReturnContainer.Deleted)
{
returned = quest.ReturnContainer.TryDropItem(quest.Creator, item, false);
//ReturnContainer.DropItem(m_RewardItem);
}
if (!returned)
{
quest.Creator.AddToBackpack(item);
}
quest.Creator.SendMessage("You receive {0} from quest {1}", item.GetType().Name, quest.Name);
}
else
{
// just delete it
item.Delete();
}
}
private static void TakeGiven(Mobile to, IXmlQuest quest, Item item)
{
if (item == null) return;
XmlSaveItem si = (XmlSaveItem)XmlAttach.FindAttachment(to, typeof(XmlSaveItem), "Given");
if (si == null)
{
XmlAttach.AttachTo(to, new XmlSaveItem("Given", item, quest.Owner));
}
else
{
si.SavedItem = item;
si.WasOwnedBy = quest.Owner;
}
// just delete it
//item.Delete();
}
public static object CreateItem(IEntity from, string action, out string status_str, Type typerestrict)
{
status_str = null;
if (action == null || action.Length <= 0 || from == null) return null;
XmlSpawner.SpawnObject TheSpawn = new XmlSpawner.SpawnObject(null, 0);
//BaseXmlSpawner.ApplyObjectStringProperties(null, action, m_TargetItem, m, m_TargetItem, out status_str);
TheSpawn.TypeName = action;
string substitutedtypeName = BaseXmlSpawner.ApplySubstitution(null, null, null, action);
string typeName = BaseXmlSpawner.ParseObjectType(substitutedtypeName);
if (BaseXmlSpawner.IsTypeOrItemKeyword(typeName))
{
BaseXmlSpawner.SpawnTypeKeyword(null, TheSpawn, typeName, substitutedtypeName, true, null, from.Location, Map.Internal, out status_str);
}
else
{
// its a regular type descriptor so find out what it is
Type type = SpawnerType.GetType(typeName);
// if a type restriction has been specified then test it
if (typerestrict != null && type != null && type != typerestrict && !type.IsSubclassOf(typerestrict))
{
return null;
}
try
{
string[] arglist = BaseXmlSpawner.ParseString(substitutedtypeName, 3, "/");
object o = XmlSpawner.CreateObject(type, arglist[0], true, true);
if (o == null)
{
status_str = "invalid type specification: " + arglist[0];
}
else if (o is Mobile)
{
Mobile m = (Mobile)o;
// dont do mobiles as rewards at this point
m.Delete();
}
else if (o is Item)
{
Item item = (Item)o;
BaseXmlSpawner.AddSpawnItem(null, from, TheSpawn, item, from.Location, Map.Internal, null, false, substitutedtypeName, out status_str);
}
else if (o is XmlAttachment)
{
BaseXmlSpawner.ApplyObjectStringProperties(null, substitutedtypeName, o, from as Mobile, o, out status_str);
return o;
}
}
catch { }
}
if (TheSpawn.SpawnedObjects.Count > 0)
{
if (TheSpawn.SpawnedObjects[0] is Item)
{
return ((Item)TheSpawn.SpawnedObjects[0]);
}
else if (TheSpawn.SpawnedObjects[0] is Mobile)
{
// dont do mobiles as rewards at this point
((Mobile)(TheSpawn.SpawnedObjects[0])).Delete();
}
}
return null;
}
public static List<Item> FindXmlQuest(PlayerMobile from)
{
if (from == null || from.Deleted) return null;
if (from.Backpack == null) return null;
List<Item> packlist = from.Backpack.Items;
if (packlist == null) return null;
List<Item> itemlist = new List<Item>();
for (int i = 0; i < packlist.Count; ++i)
{
Item item = packlist[i];
if (item != null && !item.Deleted && item is IXmlQuest)
{
//found it
// add the item to the list
itemlist.Add(item);
}
// is it an XmlQuestBook?
if (item is XmlQuestBook)
{
XmlQuestBook book = item as XmlQuestBook;
// search the book
foreach (Item xi in book.Items)
{
if (xi != null && !xi.Deleted && xi is IXmlQuest)
{
itemlist.Add(xi);
}
}
}
}
// now check any item that might be held
Item held = from.Holding;
if (held != null && !held.Deleted && held is IXmlQuest)
{
//found it
// add the item to the list
itemlist.Add(held);
}
return itemlist;
}
public static void CheckArgList(string[] arglist, int argstart, object propobj, out string typestr, out int targetcount, out bool checkprop, out string status_str)
{
targetcount = 1;
checkprop = true;
status_str = null;
typestr = null;
if (arglist.Length > argstart)
{
// go through the remaining args and determine what they are
for (int i = argstart; i < arglist.Length; i++)
{
// is it a count arg or a prop arg
string[] propargs = BaseXmlSpawner.ParseString(arglist[i], 2, "<>=!");
if (propargs.Length > 1)
{
// its a prop arg
checkprop = BaseXmlSpawner.CheckPropertyString(null, propobj, arglist[i], null, out status_str);
}
else if (arglist[i] != null && arglist[i].Length > 0 && arglist[i][0] >= '0' && arglist[i][0] <= '9')
{
// its a count arg
if(!int.TryParse(arglist[i], out targetcount))
targetcount=1;
}
else
{
// its a type arg
typestr = arglist[i];
}
}
}
}
public static void ApplyCollected(Item target, IXmlQuest quest)
{
// check the quest objectives for special COLLECT keywords
string newstatestr;
bool collectstatus = false;
if (!quest.Completed1 && CheckCollectObjective(quest, target, quest.Objective1, quest.State1, out newstatestr, out collectstatus))
{
quest.State1 = newstatestr;
quest.Completed1 = collectstatus;
}
else if (!quest.Completed2 && CheckCollectObjective(quest, target, quest.Objective2, quest.State2, out newstatestr, out collectstatus))
{
quest.State2 = newstatestr;
quest.Completed2 = collectstatus;
}
else if (!quest.Completed3 && CheckCollectObjective(quest, target, quest.Objective3, quest.State3, out newstatestr, out collectstatus))
{
quest.State3 = newstatestr;
quest.Completed3 = collectstatus;
}
else if (!quest.Completed4 && CheckCollectObjective(quest, target, quest.Objective4, quest.State4, out newstatestr, out collectstatus))
{
quest.State4 = newstatestr;
quest.Completed4 = collectstatus;
}
else if (!quest.Completed5 && CheckCollectObjective(quest, target, quest.Objective5, quest.State5, out newstatestr, out collectstatus))
{
quest.State5 = newstatestr;
quest.Completed5 = collectstatus;
}
if (!quest.Deleted && quest.Owner != null && collectstatus)
{
quest.Owner.SendMessage("Quest objective completed.");
// check to see if the quest has been completed and there is a reward to be automatically handed out
quest.CheckAutoReward();
}
}
public static void Collect(Mobile m, Item target, IXmlQuest quest)
{
if (quest == null || !quest.IsValid || m != quest.Owner) return;
// check to see what was dropped onto this
if (target != null && !target.Deleted)
{
// check for party collection
Party p = null;
if (m != null && !m.Deleted && m is PlayerMobile)
{
p = Party.Get(m);
}
if (quest.PartyEnabled && p != null)
{
// go through all of the party members to find the equivalent quest items and apply the collected target item
// make a randomized order list
List<PartyMemberInfo> startlist = new List<PartyMemberInfo>();
List<PartyMemberInfo> randlist = new List<PartyMemberInfo>();
foreach (PartyMemberInfo mi in p.Members)
{
startlist.Add(mi);
}
while (randlist.Count < p.Members.Count)
{
// pick a random member from the start list
// then take them off the list
int randindex = Utility.Random(startlist.Count);
randlist.Add(startlist[randindex]);
startlist.RemoveAt(randindex);
}
foreach (PartyMemberInfo mi in randlist)
{
Mobile member = mi.Mobile;
// see if the member is in range
if (quest.PartyRange < 0 || Utility.InRange(m.Location, member.Location, quest.PartyRange))
{
// find the quest item in their packs
Item questitem = BaseXmlSpawner.SearchMobileForItem(member, quest.Name, "IXmlQuest", false);
if (questitem != null && !questitem.Deleted && questitem is IXmlQuest)
{
ApplyCollected(target, (IXmlQuest)questitem);
}
}
}
}
else
{
ApplyCollected(target, quest);
}
}
}
public static bool CheckCollectObjective(IXmlQuest quest, Item item, string objectivestr, string statestr, out string newstatestr, out bool collectstatus)
{
// format for the objective string will be COLLECT,itemtype[,count][,proptest] or COLLECTNAMED,itemname[,itemtype][,count][,proptest]
newstatestr = statestr;
collectstatus = false;
if (objectivestr == null) return false;
string[] arglist = BaseXmlSpawner.ParseString(objectivestr, 5, ",");
int targetcount = 1;
bool found = false;
bool checkprop = true;
string status_str = null;
string typestr = null;
CheckArgList(arglist, 2, item, out typestr, out targetcount, out checkprop, out status_str);
if (status_str != null) quest.Status = status_str;
if (arglist.Length > 1)
{
// collect task objective
if (arglist[0] == "COLLECT")
{
//Type targettype = SpawnerType.GetType( arglist[1] );
// test the collect requirements against the the collected item
if (item != null && !item.Deleted && BaseXmlSpawner.CheckType(item, arglist[1])/*(item.GetType() == targettype)*/ && checkprop)
{
// found a match
found = true;
}
}
else if (arglist[0] == "COLLECTNAMED")
{
if (item != null && !item.Deleted && (arglist[1] == item.Name) && checkprop &&
(typestr == null || BaseXmlSpawner.CheckType(item, typestr))
)
{
// found a match
found = true;
}
}
}
// update the objective state
if (found)
{
int current = 0;
int.TryParse(statestr, out current);
// get the current collect count and update it
int added = 0;
if (item.Stackable)
{
if (targetcount - current < item.Amount)
{
added = targetcount - current;
if (quest != null && quest.PlayerMade)
{
Item newitem = Mobile.LiftItemDupe(item, item.Amount - added);
//Item newitem = item.Dupe(added);
//if(newitem != null)
//newitem.Amount = added;
ReturnCollected(quest, newitem);
}
else
{
item.Amount -= added;
ReturnCollected(quest, item);
}
}
else
{
added = item.Amount;
// if it is a playermade quest then give the item to the creator, otherwise just delete it
ReturnCollected(quest, item);
//item.Delete();
}
}
else
{
if (targetcount - current > 0)
{
added = 1;
//item.Delete();
}
ReturnCollected(quest, item);
}
int collected = current + added;
newstatestr = String.Format("{0}", collected);
if (collected >= targetcount)
{
// collecttask completed
collectstatus = true;
}
return true;
}
else
// not a collect task
return false;
}
public static bool ApplyGiven(Mobile mob, Item target, IXmlQuest quest)
{
if (mob == null) return false;
// check the quest objectives for special GIVE keywords
string newstatestr;
bool givestatus = false;
bool found = false;
if (!quest.Completed1 && CheckGiveObjective(quest, mob, target, quest.Objective1, quest.State1, out newstatestr, out givestatus))
{
quest.State1 = newstatestr;
quest.Completed1 = givestatus;
found = true;
}
else if (!quest.Completed2 && CheckGiveObjective(quest, mob, target, quest.Objective2, quest.State2, out newstatestr, out givestatus))
{
quest.State2 = newstatestr;
quest.Completed2 = givestatus;
found = true;
}
else if (!quest.Completed3 && CheckGiveObjective(quest, mob, target, quest.Objective3, quest.State3, out newstatestr, out givestatus))
{
quest.State3 = newstatestr;
quest.Completed3 = givestatus;
found = true;
}
else if (!quest.Completed4 && CheckGiveObjective(quest, mob, target, quest.Objective4, quest.State4, out newstatestr, out givestatus))
{
quest.State4 = newstatestr;
quest.Completed4 = givestatus;
found = true;
}
else if (!quest.Completed5 && CheckGiveObjective(quest, mob, target, quest.Objective5, quest.State5, out newstatestr, out givestatus))
{
quest.State5 = newstatestr;
quest.Completed5 = givestatus;
found = true;
}
/*
if(found)
{
mob.Say("Thank you.");
} else
{
mob.Say("I have no use for this.");
}
*/
if (quest.Owner != null && found)
{
quest.Owner.SendMessage("Quest item accepted.");
}
if (!quest.Deleted && quest.Owner != null && givestatus)
{
quest.Owner.SendMessage("Quest objective completed.");
// check to see if the quest has been completed and there is a reward to be automatically handed out
quest.CheckAutoReward();
}
return found;
}
public static bool Give(Mobile from, Mobile to, Item target, IXmlQuest quest)
{
if (quest == null || !quest.IsValid) return false;
bool found = false;
// check to see what was dropped onto this
if (target != null && !target.Deleted)
{
// check for party collection
Party p = null;
if (from != null && !from.Deleted && from is PlayerMobile)
{
p = Party.Get(from);
}
if (quest.PartyEnabled && p != null)
{
// go through all of the party members to find the equivalent quest items and apply the collected target item
// make a randomized order list
List<PartyMemberInfo> startlist = new List<PartyMemberInfo>();
List<PartyMemberInfo> randlist = new List<PartyMemberInfo>();
foreach (PartyMemberInfo mi in p.Members)
{
startlist.Add(mi);
}
while (randlist.Count < p.Members.Count)
{
// pick a random member from the start list
// then take them off the list
int randindex = Utility.Random(startlist.Count);
randlist.Add(startlist[randindex]);
startlist.RemoveAt(randindex);
}
foreach (PartyMemberInfo mi in randlist)
{
Mobile member = mi.Mobile;
// see if the member is in range
if (quest.PartyRange < 0 || Utility.InRange(from.Location, member.Location, quest.PartyRange))
{
// find the quest item in their packs
Item questitem = BaseXmlSpawner.SearchMobileForItem(member, quest.Name, "IXmlQuest", false);
if (questitem != null && !questitem.Deleted && questitem is IXmlQuest)
{
if (ApplyGiven(to, target, (IXmlQuest)questitem))
{
found = true;
}
}
}
}
}
else
{
found = ApplyGiven(to, target, quest);
}
}
return found;
}
public static bool RegisterGive(Mobile from, Mobile to, Item item)
{
// check to see if this is a quest item that is to be collected
// who is dropping it?
bool found = false;
if (item != null && !item.Deleted && from is PlayerMobile)
{
List<Item> questlist = FindXmlQuest((PlayerMobile)from);
if (questlist != null)
{
// now go through the list and try to apply the dropped item
for (int i = 0; i < questlist.Count; i++)
{
if (questlist[i] is IXmlQuest)
{
if (Give(from, to, item, (IXmlQuest)questlist[i]))
{
found = true;
}
}
}
}
}
return found;
}
public static bool CheckGiveObjective(IXmlQuest quest, Mobile mob, Item item, string objectivestr, string statestr, out string newstatestr, out bool givestatus)
{
// format for the objective string will be GIVE,mobname,itemtype[,count][,proptest] or GIVENAMED,mobname,itemname[,type][,count][,proptest]
newstatestr = statestr;
givestatus = false;
if (objectivestr == null) return false;
if (mob == null || mob.Name == null) return false;
string[] arglist = BaseXmlSpawner.ParseString(objectivestr, 6, ",");
int targetcount = 1;
bool found = false;
bool checkprop = true;
string status_str = null;
string typestr = null;
CheckArgList(arglist, 3, item, out typestr, out targetcount, out checkprop, out status_str);
if (status_str != null) quest.Status = status_str;
if (arglist.Length > 1)
{
// the name of the mob must match the specified mobname
if (mob.Name != arglist[1]) return false;
}
if (arglist.Length > 2)
{
// collect task objective
if (arglist[0] == "GIVE")
{
//Type targettype = SpawnerType.GetType( arglist[2] );
// test the requirements against the the given item
if (item != null && !item.Deleted && BaseXmlSpawner.CheckType(item, arglist[2]) /*(item.GetType() == targettype)*/ && checkprop)
{
// found a match
found = true;
}
}
else if (arglist[0] == "GIVENAMED")
{
if (item != null && !item.Deleted && (arglist[2] == item.Name) && checkprop &&
(typestr == null || BaseXmlSpawner.CheckType(item, typestr))
)
{
// found a match
found = true;
}
}
}
// update the objective state
if (found)
{
int current = 0;
int.TryParse(statestr, out current);
// get the current given count and update it
int added = 0;
if (item.Stackable)
{
if (targetcount - current < item.Amount)
{
added = targetcount - current;
if (quest != null && quest.PlayerMade)
{
//Item newitem = item.Dupe(added);
Item newitem = Mobile.LiftItemDupe(item, added);
//if(newitem != null)
//newitem.Amount = added;
TakeGiven(mob, quest, newitem);
}
else
{
item.Amount -= added;
}
}
else
{
added = item.Amount;
TakeGiven(mob, quest, item);
//item.Delete();
}
}
else
{
if (targetcount - current > 0)
{
added = 1;
TakeGiven(mob, quest, item);
//item.Delete();
}
}
int collected = current + added;
newstatestr = String.Format("{0}", collected);
if (collected >= targetcount)
{
// givetask completed
givestatus = true;
}
return (added > 0);
}
else
{
// not a give task
return false;
}
}
public static bool CheckKillObjective(IXmlQuest quest, Mobile m_killed, Mobile m_killer, string objectivestr, string statestr, out string newstatestr, out bool killstatus)
{
newstatestr = statestr;
killstatus = false;
if (objectivestr == null) return false;
// format for the objective string will be KILL,mobtype[,count][,proptest] or KILLNAMED,mobname[,type][,count][,proptest]
string[] arglist = BaseXmlSpawner.ParseString(objectivestr, 5, ",");
int targetcount = 1;
bool found = false;
bool checkprop = true;
string status_str = null;
string typestr = null;
CheckArgList(arglist, 2, m_killed, out typestr, out targetcount, out checkprop, out status_str);
if (status_str != null) quest.Status = status_str;
if (arglist.Length > 1)
{
// kill task objective
if (arglist[0] == "KILL")
{
//Type targettype = SpawnerType.GetType( arglist[1] );
// test the kill requirements against the the killed mobile
if (m_killed != null && !m_killed.Deleted && BaseXmlSpawner.CheckType(m_killed, arglist[1])/*(m_killed.GetType() == targettype)*/ && checkprop)
{
// found a match
found = true;
}
}
else if (arglist[0] == "KILLNAMED")
{
if (m_killed != null && !m_killed.Deleted && (arglist[1] == m_killed.Name) && checkprop &&
(typestr == null || BaseXmlSpawner.CheckType(m_killed, typestr))
)
{
// found a match
found = true;
}
}
}
// update the objective state
if (found)
{
// get the current kill count and update it
int current = 0;
int.TryParse(statestr, out current);
int killed = current + 1;
newstatestr = String.Format("{0}", killed);
if (killed >= targetcount)
{
// killtask completed
killstatus = true; ;
}
return true;
}
else
// not a kill task
return false;
}
public static void ApplyKilled(Mobile m_killed, Mobile m_killer, IXmlQuest quest)
{
if (quest == null || !quest.IsValid) return;
string newstatestr;
bool killstatus = false;
if (!quest.Completed1 && CheckKillObjective(quest, m_killed, m_killer, quest.Objective1, quest.State1, out newstatestr, out killstatus))
{
quest.State1 = newstatestr;
quest.Completed1 = killstatus;
}
else if (!quest.Completed2 && CheckKillObjective(quest, m_killed, m_killer, quest.Objective2, quest.State2, out newstatestr, out killstatus))
{
quest.State2 = newstatestr;
quest.Completed2 = killstatus;
}
else if (!quest.Completed3 && CheckKillObjective(quest, m_killed, m_killer, quest.Objective3, quest.State3, out newstatestr, out killstatus))
{
quest.State3 = newstatestr;
quest.Completed3 = killstatus;
}
else if (!quest.Completed4 && CheckKillObjective(quest, m_killed, m_killer, quest.Objective4, quest.State4, out newstatestr, out killstatus))
{
quest.State4 = newstatestr;
quest.Completed4 = killstatus;
}
else if (!quest.Completed5 && CheckKillObjective(quest, m_killed, m_killer, quest.Objective5, quest.State5, out newstatestr, out killstatus))
{
quest.State5 = newstatestr;
quest.Completed5 = killstatus;
}
if (!quest.Deleted && quest.Owner != null && killstatus)
{
quest.Owner.SendMessage("Quest objective completed.");
// check to see if the quest has been completed and there is a reward to be automatically handed out
quest.CheckAutoReward();
}
}
public static void CheckKilled(Mobile m_killed, Mobile m_killer, Mobile member)
{
if (!(member is PlayerMobile)) return;
// search the player for IXmlQuest objects
List<Item> mobitems = FindXmlQuest((PlayerMobile)member);
if (mobitems == null) return;
for (int i = 0; i < mobitems.Count; i++)
{
// search the objects for kill requirements
if (mobitems[i] is IXmlQuest)
{
IXmlQuest quest = (IXmlQuest)mobitems[i];
if (quest != null && !quest.Deleted && quest.PartyEnabled)
{
if (member != null && !member.Deleted)
{
if (quest.PartyRange < 0 || Utility.InRange(m_killer.Location, member.Location, quest.PartyRange))
ApplyKilled(m_killed, member, quest);
}
}
else if (member != null && !member.Deleted && member == m_killer && quest != null && !quest.Deleted)
{
ApplyKilled(m_killed, m_killer, quest);
}
}
}
}
public static void OnKilledBy(OnKilledByEventArgs e)
{
RegisterKill(e.Killed, e.KilledBy);
}
public static void RegisterKill(Mobile m_killed, Mobile m_killer)
{
// check for any attachments that might support the OnBeforeKill method
XmlAttach.CheckOnBeforeKill(m_killed, m_killer);
// check for any attachments that might support the OnKill method
XmlAttach.CheckOnKill(m_killed, m_killer);
// go through all of the party members to to try to fill killquest objectives
Party p = Party.Get(m_killer);
if (p != null)
{
foreach (PartyMemberInfo mi in p.Members)
{
Mobile member = mi.Mobile;
if (member != null && member is PlayerMobile && ((PlayerMobile)member).GetFlag(CarriedXmlQuestFlag))
{
CheckKilled(m_killed, m_killer, member);
}
}
}
else
{
if (m_killer != null && m_killer is PlayerMobile && ((PlayerMobile)m_killer).GetFlag(CarriedXmlQuestFlag))
{
CheckKilled(m_killed, m_killer, m_killer);
}
}
}
public static bool CheckEscortObjective(IXmlQuest quest, Mobile m_escorted, Mobile m_escorter, string objectivestr, string statestr, out string newstatestr, out bool escortstatus)
{
newstatestr = statestr;
escortstatus = false;
if (objectivestr == null) return false;
// format for the objective string will be ESCORT[,mobname][,proptest]
string[] arglist = BaseXmlSpawner.ParseString(objectivestr, 3, ",");
if (arglist.Length > 0)
{
// is it an escort task?
if (arglist[0] != "ESCORT")
return false;
}
else
{
return false;
}
bool found = false;
int targetcount = 1;
bool checkprop = true;
string status_str = null;
if (arglist.Length > 2)
{
checkprop = BaseXmlSpawner.CheckPropertyString(null, m_escorted, arglist[2], null, out status_str);
}
if (status_str != null) quest.Status = status_str;
if (arglist.Length > 1)
{
// check the mobname, allow for empty names to match any escort
if (m_escorted != null && !m_escorted.Deleted && (arglist[1] == m_escorted.Name || (arglist[1] == null || arglist[1] == String.Empty)) && checkprop)
{
// found a match
found = true;
}
}
else
{
// no mobname so any escort will do
if (m_escorted != null && !m_escorted.Deleted && checkprop)
{
// found a match
found = true;
}
}
// update the objective state
if (found)
{
// get the current escort count and update it
int current = 0;
int.TryParse(statestr, out current);
int escorted = current + 1;
newstatestr = String.Format("{0}", escorted);
if (escorted >= targetcount)
{
// escort completed
escortstatus = true; ;
}
return true;
}
else
// not an escort task
return false;
}
public static void ApplyEscorted(Mobile m_escorted, Mobile m_escorter, IXmlQuest quest)
{
if (quest == null || !quest.IsValid) return;
string newstatestr;
bool escortstatus = false;
if (!quest.Completed1 && CheckEscortObjective(quest, m_escorted, m_escorter, quest.Objective1, quest.State1, out newstatestr, out escortstatus))
{
quest.State1 = newstatestr;
quest.Completed1 = escortstatus;
}
else if (!quest.Completed2 && CheckEscortObjective(quest, m_escorted, m_escorter, quest.Objective2, quest.State2, out newstatestr, out escortstatus))
{
quest.State2 = newstatestr;
quest.Completed2 = escortstatus;
}
else if (!quest.Completed3 && CheckEscortObjective(quest, m_escorted, m_escorter, quest.Objective3, quest.State3, out newstatestr, out escortstatus))
{
quest.State3 = newstatestr;
quest.Completed3 = escortstatus;
}
else if (!quest.Completed4 && CheckEscortObjective(quest, m_escorted, m_escorter, quest.Objective4, quest.State4, out newstatestr, out escortstatus))
{
quest.State4 = newstatestr;
quest.Completed4 = escortstatus;
}
else if (!quest.Completed5 && CheckEscortObjective(quest, m_escorted, m_escorter, quest.Objective5, quest.State5, out newstatestr, out escortstatus))
{
quest.State5 = newstatestr;
quest.Completed5 = escortstatus;
}
if (!quest.Deleted && quest.Owner != null && escortstatus)
{
quest.Owner.SendMessage("Quest objective completed.");
// check to see if the quest has been completed and there is a reward to be automatically handed out
quest.CheckAutoReward();
}
}
public static void CheckEscorted(Mobile m_escorted, Mobile m_escorter, Mobile member)
{
if (!(member is PlayerMobile)) return;
// search the player for IXmlQuest objects
List<Item> mobitems = FindXmlQuest((PlayerMobile)member);
if (mobitems == null) return;
for (int i = 0; i < mobitems.Count; i++)
{
if (mobitems[i] is IXmlQuest)
{
// search the objects for escort requirements
IXmlQuest quest = (IXmlQuest)mobitems[i];
if (quest != null && !quest.Deleted && quest.PartyEnabled)
{
if (member != null && !member.Deleted)
{
if (quest.PartyRange < 0 || Utility.InRange(m_escorter.Location, member.Location, quest.PartyRange))
{
ApplyEscorted(m_escorted, member, quest);
}
}
}
else if (member != null && !member.Deleted && member == m_escorter && quest != null && !quest.Deleted)
{
ApplyEscorted(m_escorted, m_escorter, quest);
}
}
}
}
public static void RegisterEscort(Mobile m_escorted, Mobile m_escorter)
{
// go through all of the party members to to try to fill escort objectives
Party p = Party.Get(m_escorter);
if (p != null)
{
foreach (PartyMemberInfo mi in p.Members)
{
Mobile member = mi.Mobile;
if (member != null && member is PlayerMobile && ((PlayerMobile)member).GetFlag(CarriedXmlQuestFlag))
{
CheckEscorted(m_escorted, m_escorter, member);
}
}
}
else
{
if (m_escorter != null && m_escorter is PlayerMobile && ((PlayerMobile)m_escorter).GetFlag(CarriedXmlQuestFlag))
{
CheckEscorted(m_escorted, m_escorter, m_escorter);
}
}
}
// Unused...was it meant to do anything?!
/*public static Hashtable VisitSectorList = new Hashtable();
public static void RegisterMove(PlayerMobile m_player)
{
if (m_player == null || m_player.Map == null) return;
// check for any attachments that might support the OnMove method
//XmlAttach.CheckOnMove(m_player);
// check to see if the current sector that the player is in, is registered in the VISIT sector list
Sector newSector = m_player.Map.GetSector(m_player.Location);
if (VisitSectorList != null && VisitSectorList.Contains(newSector))
{
// check to see if the player has a quest with a VISIT type objective
if (m_player.GetFlag(CarriedXmlQuestFlag))
{
CheckVisited(m_player);
}
}
}*/
public static bool CheckVisitObjective(IXmlQuest quest, PlayerMobile m_player, string objectivestr, string statestr, out string newstatestr, out bool visitstatus)
{
newstatestr = statestr;
visitstatus = false;
if (objectivestr == null) return false;
// format for the objective string will be VISIT,x,y,range[,duration]
string[] arglist = BaseXmlSpawner.ParseString(objectivestr, 5, ",");
bool found = false;
int targetcount = 1;
string status_str = null;
if (status_str != null) quest.Status = status_str;
if (arglist.Length > 3)
{
// escort task objective
if (arglist[0] == "VISIT")
{
double duration = 0; // duration in minutes
// get the coords
int x = 0;
if(!int.TryParse(arglist[1], out x))
status_str = "invalid VISIT x";
int y = 0;
if(!int.TryParse(arglist[2], out y))
status_str = "invalid VISIT y";
int range = 0;
if(!int.TryParse(arglist[3], out range))
status_str = "invalid VISIT range";
if (arglist.Length > 4)
{
if(!double.TryParse(arglist[4], NumberStyles.Any, CultureInfo.InvariantCulture, out duration))
status_str = "invalid VISIT duration";
}
// check them against the players current location
if (m_player != null && m_player.InRange(new Point2D(x, y), range))
{
if (duration > 0)
{
// is there already a timer started on the quest object?
}
else
{
found = true;
}
// if it is in range, then start the timer
}
}
}
// update the objective state
if (found)
{
// get the current visitation count and update it
int current = 0;
int.TryParse(statestr, out current);
int visited = current + 1;
newstatestr = String.Format("{0}", visited);
if (visited >= targetcount)
{
// visitation completed
visitstatus = true; ;
}
return true;
}
else
// not a visitation task
return false;
}
public static void ApplyVisited(PlayerMobile m_player, IXmlQuest quest)
{
if (quest == null || !quest.IsValid) return;
string newstatestr;
bool visitstatus = false;
if (!quest.Completed1 && CheckVisitObjective(quest, m_player, quest.Objective1, quest.State1, out newstatestr, out visitstatus))
{
quest.State1 = newstatestr;
quest.Completed1 = visitstatus;
}
else if (!quest.Completed2 && CheckVisitObjective(quest, m_player, quest.Objective2, quest.State2, out newstatestr, out visitstatus))
{
quest.State2 = newstatestr;
quest.Completed2 = visitstatus;
}
else if (!quest.Completed3 && CheckVisitObjective(quest, m_player, quest.Objective2, quest.State2, out newstatestr, out visitstatus))
{
quest.State3 = newstatestr;
quest.Completed3 = visitstatus;
}
else if (!quest.Completed4 && CheckVisitObjective(quest, m_player, quest.Objective4, quest.State4, out newstatestr, out visitstatus))
{
quest.State4 = newstatestr;
quest.Completed4 = visitstatus;
}
else if (!quest.Completed5 && CheckVisitObjective(quest, m_player, quest.Objective5, quest.State5, out newstatestr, out visitstatus))
{
quest.State5 = newstatestr;
quest.Completed5 = visitstatus;
}
if (!quest.Deleted && quest.Owner != null && visitstatus)
{
quest.Owner.SendMessage("Quest objective completed.");
// check to see if the quest has been completed and there is a reward to be automatically handed out
quest.CheckAutoReward();
}
}
public static void CheckVisited(PlayerMobile m_player)
{
// search the player for IXmlQuest objects
List<Item> mobitems = FindXmlQuest(m_player);
if (mobitems == null) return;
for (int i = 0; i < mobitems.Count; i++)
{
if (mobitems[i] is IXmlQuest)
{
// search the objects for visitation requirements
IXmlQuest quest = (IXmlQuest)mobitems[i];
if (quest != null && !quest.Deleted)
{
ApplyVisited(m_player, quest);
}
}
}
}
public static bool VerifyObjective(string[] arglist, out string status_str)
{
status_str = null;
if (arglist == null || arglist.Length < 1)
{
return true;
}
bool checkprop;
int targetcount;
string typestr = null;
switch (arglist[0])
{
case "COLLECT":
case "KILL":
XmlQuest.CheckArgList(arglist, 2, null, out typestr, out targetcount, out checkprop, out status_str);
if (arglist.Length > 1)
{
if (SpawnerType.GetType(arglist[1]) == null)
{
status_str = "Invalid type: " + arglist[1];
return false;
}
}
else
{
status_str = arglist[0] + "missing args";
return false;
}
break;
case "COLLECTNAMED":
case "KILLNAMED":
XmlQuest.CheckArgList(arglist, 2, null, out typestr, out targetcount, out checkprop, out status_str);
if (arglist.Length < 1)
{
status_str = arglist[0] + "missing args";
return false;
}
break;
case "GIVENAMED":
XmlQuest.CheckArgList(arglist, 3, null, out typestr, out targetcount, out checkprop, out status_str);
if (arglist.Length < 1)
{
status_str = arglist[0] + "missing args";
return false;
}
break;
case "GIVE":
XmlQuest.CheckArgList(arglist, 3, null, out typestr, out targetcount, out checkprop, out status_str);
if (arglist.Length > 2)
{
if (SpawnerType.GetType(arglist[2]) == null)
{
status_str = "Invalid type: " + arglist[2];
return false;
}
}
else
{
status_str = arglist[0] + "missing args";
return false;
}
break;
}
// check the validity of the typestr
if (typestr != null)
{
if (SpawnerType.GetType(typestr) == null)
{
status_str = "Invalid type: " + typestr;
return false;
}
}
return true;
}
public static void VerifyObjectives(IXmlQuest quest)
{
string status_str;
// go through each objective and test the args
VerifyObjective(BaseXmlSpawner.ParseString(quest.Objective1, 6, ","), out status_str);
if (status_str != null) quest.Status = status_str;
VerifyObjective(BaseXmlSpawner.ParseString(quest.Objective2, 6, ","), out status_str);
if (status_str != null) quest.Status = status_str;
VerifyObjective(BaseXmlSpawner.ParseString(quest.Objective3, 6, ","), out status_str);
if (status_str != null) quest.Status = status_str;
VerifyObjective(BaseXmlSpawner.ParseString(quest.Objective4, 6, ","), out status_str);
if (status_str != null) quest.Status = status_str;
VerifyObjective(BaseXmlSpawner.ParseString(quest.Objective5, 6, ","), out status_str);
if (status_str != null) quest.Status = status_str;
}
}
}