Files
abysmal-isle/Scripts/Services/XmlSpawner/XmlSpawner Core/XmlQuest/XmlQuestToken.cs
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

1895 lines
64 KiB
C#

using System;
using Server;
using Server.Gumps;
using Server.Network;
using Server.Mobiles;
using System.IO;
using System.Collections.Generic;
using Server.Targeting;
using Server.Engines.PartySystem;
using System.Data;
using System.Xml;
using Server.Engines.XmlSpawner2;
/*
** XmlQuestToken class
**
** Version 1.10
** updated 10/26/04
** ArteGordon
**
** Version 1.10
** updated 10/26/04
** - modified RewardString to only support item rewards and added the new AttachmentString property for specifying attachment rewards.
**
** Version 1.09
** updated 9/03/04
** - added the autoreward and rewarditem properties that allow rewards to be automatically created and given upon quest completion
**
** Version 1.08
** updated 7/31/04
** - added the Description1-5 property to allow the quest objective descriptions to be explicitly specified. When this string is defined it will override the default
** description provided for the different types of quest objectives.
**
** Version 1.07
** updated 7/28/04
** - add support for an additional property test argument to the quest keywords
** - mobs no longer say "Thank you", or "I have no need for that." when given items for GIVE type quests.
**
** Version 1.06
** updated 7/07/04
** - Added the GIVE type quest objective. Using an objective string of the type "GIVE,mobname,item[,count]" or "GIVENAMED,mobname,itemname[,count]" will produce an objective
** that is satisfied when the specified item(s) are dragged and dropped onto the named mob.
** - Added the ESCORT type quest objective. Using an objective string of the type "ESCORT,mobname" will produce an objective
** that is satisfied when the specified TalkingBaseEscortable class mob is successfully escorted to its destination.
** Note, the destination is specified by setting the Destination property on the escort to a region name.
** - changed the rules for invalid XmlQuestTokens to eliminate hording or trading so that they can no longer be placed in containers and will automatically
** return to the player's pack if the player attempts to place them in any invalid location (such as another container, a bankbox, or another player).
** If they are placed on ground they will be automatically deleted.
** - added optimizations for KILL type quests in which only players that are flagged as carrying XmlQuestTokens are checked on kills.
**
** Version 1.05
** updated 4/30/04
** - Added the RewardString property
**
** Version 1.04
** updated 3/25/04
** - Added the LoadConfig and ConfigFile properties that allow XmlQuestTokens to read their configuration information from an XML file.
** - Moved the TitleString and NoteString properties from the QuestNote class to the XmlQuestToken class.
**
** Version 1.03
** updated 3/25/04
** - Added the PartyEnabled and PartyRange properties that allow party members to benefit from KILL and COLLECT keywords.
**
** Version 1.02
** updated 3/20/04
** - fixed the COLLECT and COLLECTNAMED keywords to remove non-stackable items after collecting. Thanks to nix4 for pointing this out.
**
* Version 1.01
** updated 2/26/04
** - modified expiration time reporting format
** - added State properties to support more complex objective status information
** - added killtask support with special objective specification keywords KILL,mobtype,count and KILLNAMED,mobname,count
** - added collecttask support with special objective specification keywords COLLECT,itemtype,count and COLLECTNAMED,itemname,count
**
** Version 1.0
** updated 1/07/04
*/
namespace Server.Items
{
public class XmlQuestTokenPack : Container
{
public override bool OnDragDrop(Mobile from, Item dropped)
{
return false;
}
public override bool OnDragDropInto(Mobile from, Item item, Point3D p)
{
return false;
}
#if(NEWPARENT)
public override void OnAdded(IEntity target)
#else
public override void OnAdded(object target)
#endif
{
base.OnAdded(target);
UpdateTotal(this, TotalType.Weight, 0);
UpdateTotal(this, TotalType.Gold, 0);
UpdateTotal(this, TotalType.Items, 0);
}
public sealed class ForcedContainerContent : Packet
{
public ForcedContainerContent(Mobile beholder, Item beheld)
: base(0x3C)
{
List<Item> items = beheld.Items;
int count = items.Count;
this.EnsureCapacity(5 + (count * 19));
long pos = m_Stream.Position;
int written = 0;
m_Stream.Write((ushort)0);
for (int i = 0; i < count; ++i)
{
Item child = items[i];
if (!child.Deleted )
{
Point3D loc = child.Location;
ushort cid = (ushort)child.ItemID;
if (cid > 0x3FFF)
cid = 0x9D7;
m_Stream.Write((int)child.Serial);
m_Stream.Write((ushort)cid);
m_Stream.Write((byte)0); // signed, itemID offset
m_Stream.Write((ushort)child.Amount);
m_Stream.Write((short)loc.X);
m_Stream.Write((short)loc.Y);
m_Stream.Write((int)beheld.Serial);
m_Stream.Write((ushort)child.Hue);
++written;
}
}
m_Stream.Seek(pos, SeekOrigin.Begin);
m_Stream.Write((ushort)written);
}
}
public override void DisplayTo(Mobile to)
{
if (to == null) return;
to.Send(new ContainerDisplay(this));
to.Send(new ForcedContainerContent(to, this));
if (ObjectPropertyList.Enabled)
{
List<Item> items = this.Items;
for (int i = 0; i < items.Count; ++i)
to.Send(((Item)items[i]).OPLPacket);
}
}
public XmlQuestTokenPack()
: base(0x9B2)
{
Weight = 0;
}
public XmlQuestTokenPack(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public abstract class XmlQuestToken : Item, IXmlQuest
{
//public const PlayerFlag CarriedXmlQuestFlag = (PlayerFlag)0x00100000;
private bool m_wasMoved = false;
private double m_ExpirationDuration;
private DateTime m_TimeCreated;
private string m_Objective1;
private string m_Objective2;
private string m_Objective3;
private string m_Objective4;
private string m_Objective5;
private string m_Description1;
private string m_Description2;
private string m_Description3;
private string m_Description4;
private string m_Description5;
private bool m_Completed1 = false;
private bool m_Completed2 = false;
private bool m_Completed3 = false;
private bool m_Completed4 = false;
private bool m_Completed5 = false;
private string m_State1;
private string m_State2;
private string m_State3;
private string m_State4;
private string m_State5;
private bool m_PartyEnabled = false;
private int m_PartyRange = -1;
private string m_ConfigFile;
private string m_NoteString;
private string m_TitleString;
private string m_RewardString;
private string m_AttachmentString;
private PlayerMobile m_Owner;
private string m_SkillTrigger = null;
private bool m_Repeatable = true;
private TimeSpan m_NextRepeatable;
private Item m_RewardItem;
private XmlAttachment m_RewardAttachment;
private int m_RewardAttachmentSerialNumber;
private bool m_AutoReward = false;
private Container m_Pack;
private bool m_CanSeeReward = false;
private bool m_PlayerMade = false;
private PlayerMobile m_Creator;
private Container m_ReturnContainer;
private string m_status_str;
private int m_QuestDifficulty = 1;
public XmlQuestToken(Serial serial)
: base(serial)
{
}
public XmlQuestToken()
{
//LootType = LootType.Blessed;
TimeCreated = DateTime.UtcNow;
}
public XmlQuestToken(int itemID)
{
ItemID = itemID;
//LootType = LootType.Blessed;
TimeCreated = DateTime.UtcNow;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)14); // version
// version 14
if (m_Journal == null || m_Journal.Count == 0)
{
writer.Write((int)0);
}
else
{
writer.Write((int)m_Journal.Count);
foreach (XmlQuest.JournalEntry e in m_Journal)
{
writer.Write(e.EntryID);
writer.Write(e.EntryText);
}
}
// version 13
writer.Write(m_Repeatable);
// version 12
writer.Write(m_QuestDifficulty);
// version 11
writer.Write(m_AttachmentString);
// version 10
writer.Write(m_NextRepeatable);
// version 9
if (m_RewardAttachment != null)
writer.Write(m_RewardAttachment.Serial.Value);
else
writer.Write((int)0);
// version 8
writer.Write(m_ReturnContainer);
// version 7
writer.Write(m_Pack);
writer.Write(m_RewardItem);
writer.Write(m_AutoReward);
writer.Write(m_CanSeeReward);
writer.Write(m_PlayerMade);
writer.Write(m_Creator);
// version 6
writer.Write(m_Description1);
writer.Write(m_Description2);
writer.Write(m_Description3);
writer.Write(m_Description4);
writer.Write(m_Description5);
// version 5
writer.Write(m_Owner);
// version 4
writer.Write(m_RewardString);
// version 3
writer.Write(m_ConfigFile);
writer.Write(m_NoteString); // moved from the QuestNote class
writer.Write(m_TitleString); // moved from the QuestNote class
// version 2
writer.Write(m_PartyEnabled);
writer.Write(m_PartyRange);
// version 1
writer.Write(m_State1);
writer.Write(m_State2);
writer.Write(m_State3);
writer.Write(m_State4);
writer.Write(m_State5);
// version 0
writer.Write(m_wasMoved);
writer.Write(m_ExpirationDuration);
writer.Write(m_TimeCreated);
writer.Write(m_Objective1);
writer.Write(m_Objective2);
writer.Write(m_Objective3);
writer.Write(m_Objective4);
writer.Write(m_Objective5);
writer.Write(m_Completed1);
writer.Write(m_Completed2);
writer.Write(m_Completed3);
writer.Write(m_Completed4);
writer.Write(m_Completed5);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 14:
{
int nentries = reader.ReadInt();
if (nentries > 0)
{
m_Journal = new List<XmlQuest.JournalEntry>();
for (int i = 0; i < nentries; i++)
{
string entryID = reader.ReadString();
string entryText = reader.ReadString();
m_Journal.Add(new XmlQuest.JournalEntry(entryID, entryText));
}
}
goto case 13;
}
case 13:
{
m_Repeatable = reader.ReadBool();
goto case 12;
}
case 12:
{
m_QuestDifficulty = reader.ReadInt();
goto case 11;
}
case 11:
{
m_AttachmentString = reader.ReadString();
goto case 10;
}
case 10:
{
m_NextRepeatable = reader.ReadTimeSpan();
goto case 9;
}
case 9:
{
m_RewardAttachmentSerialNumber = reader.ReadInt();
goto case 8;
}
case 8:
{
this.m_ReturnContainer = (Container)reader.ReadItem();
goto case 7;
}
case 7:
{
this.m_Pack = (Container)reader.ReadItem();
this.m_RewardItem = reader.ReadItem();
this.m_AutoReward = reader.ReadBool();
this.m_CanSeeReward = reader.ReadBool();
this.m_PlayerMade = reader.ReadBool();
this.m_Creator = reader.ReadMobile() as PlayerMobile;
goto case 6;
}
case 6:
{
this.m_Description1 = reader.ReadString();
this.m_Description2 = reader.ReadString();
this.m_Description3 = reader.ReadString();
this.m_Description4 = reader.ReadString();
this.m_Description5 = reader.ReadString();
goto case 5;
}
case 5:
{
this.m_Owner = reader.ReadMobile() as PlayerMobile;
goto case 4;
}
case 4:
{
this.m_RewardString = reader.ReadString();
goto case 3;
}
case 3:
{
this.m_ConfigFile = reader.ReadString();
this.m_NoteString = reader.ReadString();
this.m_TitleString = reader.ReadString();
goto case 2;
}
case 2:
{
this.m_PartyEnabled = reader.ReadBool();
this.m_PartyRange = reader.ReadInt();
goto case 1;
}
case 1:
{
this.m_State1 = reader.ReadString();
this.m_State2 = reader.ReadString();
this.m_State3 = reader.ReadString();
this.m_State4 = reader.ReadString();
this.m_State5 = reader.ReadString();
goto case 0;
}
case 0:
{
this.m_wasMoved = reader.ReadBool();
this.Expiration = reader.ReadDouble();
this.m_TimeCreated = reader.ReadDateTime();
this.m_Objective1 = reader.ReadString();
this.m_Objective2 = reader.ReadString();
this.m_Objective3 = reader.ReadString();
this.m_Objective4 = reader.ReadString();
this.m_Objective5 = reader.ReadString();
this.m_Completed1 = reader.ReadBool();
this.m_Completed2 = reader.ReadBool();
this.m_Completed3 = reader.ReadBool();
this.m_Completed4 = reader.ReadBool();
this.m_Completed5 = reader.ReadBool();
}
break;
}
}
public static void Initialize()
{
foreach (Item item in World.Items.Values)
{
if (item is XmlQuestToken)
{
XmlQuestToken t = item as XmlQuestToken;
if (t.Pack != null && !t.Pack.Deleted)
{
t.UpdateWeight();
t.UpdateTotal(t.Pack, TotalType.Weight, 0);
t.UpdateTotal(t.Pack, TotalType.Gold, 0);
t.RestoreRewardAttachment();
}
}
}
}
public override void OnDoubleClick(Mobile from)
{
base.OnDoubleClick(from);
if (!(from is PlayerMobile)) return;
if (PlayerMade && (from == Creator) && (from == Owner))
{
from.SendGump(new XmlPlayerQuestGump((PlayerMobile)from, this));
}
}
public override bool OnDroppedToWorld(Mobile from, Point3D point)
{
bool returnvalue = base.OnDroppedToWorld(from, point);
from.SendGump(new XmlConfirmDeleteGump(from, this));
//m_wasMoved = true;
//CheckOwnerFlag();
//Invalidate();
return false;
//return returnvalue;
}
public override void OnDelete()
{
// remove any temporary quest attachments associated with this quest and quest owner
XmlQuest.RemoveTemporaryQuestObjects(Owner, Name);
base.OnDelete();
// remove any reward items that might be attached to this
ReturnReward();
// and remove any pack
if (Pack != null)
{
Pack.Delete();
}
CheckOwnerFlag();
}
public override void OnItemLifted(Mobile from, Item item)
{
base.OnItemLifted(from, item);
if (from is PlayerMobile && PlayerMade && (Owner != null) && (Owner == Creator))
{
LootType = LootType.Regular;
}
else
if (from is PlayerMobile && Owner == null)
{
Owner = from as PlayerMobile;
LootType = LootType.Blessed;
// flag the owner as carrying a questtoken
Owner.SetFlag(XmlQuest.CarriedXmlQuestFlag, true);
}
}
#if(NEWPARENT)
public override void OnAdded(IEntity target)
#else
public override void OnAdded(object target)
#endif
{
base.OnAdded(target);
if ((target != null) && target is Container)
{
// find the parent of the container
// note, the only valid additions are to the player pack or a questbook. Anything else is invalid. This is to avoid exploits involving storage or transfer of questtokens
// make an exception for playermade quests that can be put on playervendors
object parentOfTarget = ((Container)target).Parent;
// if this is a QuestBook then allow additions if it is in a players pack or it is a player quest
if ((parentOfTarget != null) && parentOfTarget is Container && target is XmlQuestBook)
{
parentOfTarget = ((Container)parentOfTarget).Parent;
}
// check to see if it can be added.
// allow playermade quests to be placed in playervendors or in xmlquestbooks that are in the world (supports the playerquestboards)
if (PlayerMade && (((parentOfTarget != null) && parentOfTarget is PlayerVendor) ||
((parentOfTarget == null) && target is XmlQuestBook)))
{
CheckOwnerFlag();
Owner = null;
LootType = LootType.Regular;
}
else
if ((parentOfTarget != null) && (parentOfTarget is PlayerMobile) && PlayerMade && (Owner != null) && ((Owner == Creator) || (Creator == null)))
{
// check the old owner
CheckOwnerFlag();
Owner = parentOfTarget as PlayerMobile;
// first owner will become creator by default
if (Creator == null)
Creator = Owner;
LootType = LootType.Blessed;
// flag the new owner as carrying a questtoken
Owner.SetFlag(XmlQuest.CarriedXmlQuestFlag, true);
}
else
if ((parentOfTarget != null) && (parentOfTarget is PlayerMobile))
{
if (Owner == null)
{
Owner = parentOfTarget as PlayerMobile;
LootType = LootType.Blessed;
// flag the owner as carrying a questtoken
Owner.SetFlag(XmlQuest.CarriedXmlQuestFlag, true);
}
else
if ((parentOfTarget as PlayerMobile != Owner) || (target is BankBox))
{
// tried to give it to another player or placed it in the players bankbox. try to return it to the owners pack
Owner.AddToBackpack(this);
/*
// this has been added to a player who is not the owner so invalidate it
WasMoved = true;
CheckOwnerFlag();
Invalidate();
*/
}
}
else
{
if (Owner != null)
{
// try to return it to the owners pack
Owner.AddToBackpack(this);
}
// allow placement into npcs or drop on their corpses when owner is null
else
if (!(parentOfTarget is Mobile) && !(target is Corpse) && parentOfTarget != null)
{
// in principle this should never be reached
// invalidate the token
WasMoved = true;
CheckOwnerFlag();
Invalidate();
}
}
}
}
private List<XmlQuest.JournalEntry> m_Journal;
public List<XmlQuest.JournalEntry> Journal { get { return m_Journal; } set { m_Journal = value; } }
private static char[] colondelim = new char[1] { ':' };
public string AddJournalEntry
{
set
{
if (value == null) return;
// parse the value
string[] args = value.Split(colondelim, 2);
if (args == null) return;
string entryID = null;
string entryText = null;
if (args.Length > 0)
{
entryID = args[0].Trim();
}
if (entryID == null || entryID.Length == 0) return;
if (args.Length > 1)
{
entryText = args[1].Trim();
}
// allocate a new journal if none exists
if (m_Journal == null) m_Journal = new List<XmlQuest.JournalEntry>();
// go through the existing journal to find a matching ID
XmlQuest.JournalEntry foundEntry = null;
foreach (XmlQuest.JournalEntry e in m_Journal)
{
if (e.EntryID == entryID)
{
foundEntry = e;
break;
}
}
if (foundEntry != null)
{
if (entryText == null || entryText.Length == 0)
{
// delete the entry
m_Journal.Remove(foundEntry);
}
else
{
// just replace the text
foundEntry.EntryText = entryText;
}
}
else
{
if (entryText != null && entryText.Length != 0)
{
// add the new entry
m_Journal.Add(new XmlQuest.JournalEntry(entryID, entryText));
}
}
}
}
private void QuestCompletionAttachment()
{
bool complete = IsCompleted;
// is this quest repeatable
if ((!Repeatable || NextRepeatable > TimeSpan.Zero) && complete)
{
double expiresin = Repeatable ? NextRepeatable.TotalMinutes : 0;
// then add an attachment indicating that it has already been done
XmlAttach.AttachTo(Owner, new XmlQuestAttachment(this.Name, expiresin));
}
// have quest points been enabled?
if (XmlQuest.QuestPointsEnabled && complete && !PlayerMade)
{
XmlQuestPoints.GiveQuestPoints(Owner, this);
}
}
private void PackItem(Item item)
{
if ((m_Pack == null || m_Pack.Deleted) && (Owner != null) /* && (this.RootParent is Mobile) */)
{
m_Pack = new XmlQuestTokenPack();
m_Pack.Layer = Layer.Invalid;
//m_Pack.Parent = Owner;
m_Pack.Parent = this;
//m_Pack.Map = Owner.Map;
m_Pack.Map = this.Map;
m_Pack.Location = this.Location;
}
if ((m_Pack != null) && !m_Pack.Deleted)
{
m_Pack.DropItem(item);
PackItemsMovable(m_Pack, false);
UpdateTotal(m_Pack, TotalType.Weight, 0);
UpdateTotal(m_Pack, TotalType.Gold, 0);
}
// make sure the weight and gold of the questtoken is updated to reflect the weight of added rewards in playermade quests to avoid
// exploits where quests are used as zero weight containers
UpdateWeight();
}
private void CalculateWeight(Item target)
{
if (target is Container)
{
int gold = 0;
int weight = 0;
int nitems = 0;
foreach (Item i in ((Container)target).FindItemsByType(typeof(Item), false))
{
// make sure gold amount is consistent with totalgold
if (i is Gold)
{
UpdateTotal(i, TotalType.Gold, i.Amount);
}
if (i is Container)
{
CalculateWeight(i);
weight += i.TotalWeight + (int)i.Weight;
gold += i.TotalGold;
nitems += i.TotalItems + 1;
}
else
{
weight += (int)(i.Weight * i.Amount);
gold += i.TotalGold;
nitems += 1;
}
}
UpdateTotal((Container)target, TotalType.Weight, weight);
UpdateTotal((Container)target, TotalType.Gold, gold);
UpdateTotal((Container)target, TotalType.Items, nitems);
}
}
private void UpdateWeight()
{
// update the weight of the reward item itself
CalculateWeight(m_RewardItem);
// make sure the weight and gold of the questtoken is updated to reflect the weight of added rewards
if (m_RewardItem != null && !m_RewardItem.Deleted && PlayerMade)
{
if (m_RewardItem is Container)
{
UpdateTotal(this, TotalType.Weight, m_RewardItem.TotalWeight + (int)m_RewardItem.Weight);
UpdateTotal(this, TotalType.Gold, m_RewardItem.TotalGold);
}
else
{
UpdateTotal(this, TotalType.Weight, (int)(m_RewardItem.Weight * m_RewardItem.Amount));
UpdateTotal(this, TotalType.Gold, m_RewardItem.TotalGold);
}
}
else
{
UpdateTotal(this, TotalType.Weight, 0);
UpdateTotal(this, TotalType.Gold, 0);
}
}
private void ReturnReward()
{
if (m_RewardItem != null)
{
CheckRewardItem();
// if this was player made, then return the item to the creator
if (PlayerMade && (Creator != null) && !Creator.Deleted)
{
m_RewardItem.Movable = true;
if (m_Pack != null && !m_Pack.Deleted)
{
// make sure all of the items in the pack are movable as well
PackItemsMovable(m_Pack, true);
}
bool returned = false;
//RefreshPackLocation(Creator, false);
if ((ReturnContainer != null) && !ReturnContainer.Deleted)
{
returned = ReturnContainer.TryDropItem(Creator, m_RewardItem, false);
//ReturnContainer.DropItem(m_RewardItem);
}
if (!returned)
{
returned = Creator.AddToBackpack(m_RewardItem);
}
if (returned)
{
Creator.SendMessage("Your reward {0} was returned from quest {1}", m_RewardItem.GetType().Name, Name);
//AddMobileWeight(Creator, m_RewardItem);
}
else
{
Creator.SendMessage("Attempted to return reward {0} from quest {1} : containers full.", m_RewardItem.GetType().Name, Name);
}
}
else
{
// just delete it
m_RewardItem.Delete();
}
m_RewardItem = null;
UpdateWeight();
}
if (m_RewardAttachment != null)
{
// delete any remaining attachments
m_RewardAttachment.Delete();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public PlayerMobile Owner
{
get { return m_Owner; }
set { m_Owner = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public new string Name
{
get
{
if (PlayerMade)
{
return "PQ: " + base.Name;
}
else
{
return base.Name;
}
}
set
{
base.Name = value;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public PlayerMobile Creator
{
get { return m_Creator; }
set { m_Creator = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public int Difficulty
{
get { return m_QuestDifficulty; }
set { m_QuestDifficulty = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string NoteString
{
get { return m_NoteString; }
set { m_NoteString = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public bool AutoReward
{
get { return m_AutoReward; }
set { m_AutoReward = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public bool CanSeeReward
{
// dont allow rewards to be seen on xmlquesttokens
get { return false; }
set { }
}
/*
[CommandProperty( AccessLevel.GameMaster )]
public bool CanSeeReward
{
get{ return m_CanSeeReward; }
set { m_CanSeeReward = value; }
}
*/
[CommandProperty(AccessLevel.GameMaster)]
public bool PlayerMade
{
get { return m_PlayerMade; }
set { m_PlayerMade = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public Container ReturnContainer
{
get { return m_ReturnContainer; }
set { m_ReturnContainer = value; }
}
public Container Pack
{
get { return m_Pack; }
}
private void PackItemsMovable(Container pack, bool canmove)
{
if (pack == null) return;
Item[] itemlist = pack.FindItemsByType(typeof(Item), true);
if (itemlist != null)
{
for (int i = 0; i < itemlist.Length; i++)
{
itemlist[i].Movable = canmove;
}
}
}
private void RestoreRewardAttachment()
{
m_RewardAttachment = XmlAttach.FindAttachmentBySerial(m_RewardAttachmentSerialNumber);
}
public XmlAttachment RewardAttachment
{
get
{
// if the reward item is not set, and the reward string is specified, then use the reward string to construct and assign the
// reward item
// dont allow player made quests to use the rewardstring creation feature
if (m_RewardAttachment != null && m_RewardAttachment.Deleted) m_RewardAttachment = null;
if ((m_RewardAttachment == null || m_RewardAttachment.Deleted) &&
(m_AttachmentString != null) && !PlayerMade)
{
object o = XmlQuest.CreateItem(this, m_AttachmentString, out m_status_str, typeof(XmlAttachment));
if (o is Item)
{
// should never get here
((Item)o).Delete();
}
else
if (o is XmlAttachment)
{
m_RewardAttachment = o as XmlAttachment;
m_RewardAttachment.OwnedBy = this;
}
}
return m_RewardAttachment;
}
set
{
// get rid of any existing attachment
if (m_RewardAttachment != null && !m_RewardAttachment.Deleted)
{
m_RewardAttachment.Delete();
}
m_RewardAttachment = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public Item RewardItem
{
get
{
// if the reward item is not set, and the reward string is specified, then use the reward string to construct and assign the
// reward item
// dont allow player made quests to use the rewardstring creation feature
if ((m_RewardItem == null || m_RewardItem.Deleted) &&
(m_RewardString != null) && !PlayerMade)
{
string status_str;
object o = XmlQuest.CreateItem(this, m_RewardString, out status_str, typeof(Item));
if (o is Item)
{
m_RewardItem = o as Item;
}
else
if (o is XmlAttachment)
{
// should never get here
((XmlAttachment)o).Delete();
}
}
// place it in the xmlquesttoken pack if it isnt already there
if ((m_RewardItem != null && !m_RewardItem.Deleted) && ((Pack == null) || Pack.Deleted || (m_RewardItem.Parent != Pack)))
{
PackItem(m_RewardItem);
}
return m_RewardItem;
}
set
{
// get rid of any existing reward item if it has been assigned
if (m_RewardItem != null && !m_RewardItem.Deleted)
{
ReturnReward();
}
// and assign the new item
m_RewardItem = value;
// and put it in the xmlquesttoken pack
if (m_RewardItem != null && !m_RewardItem.Deleted)
{
PackItem(m_RewardItem);
}
// is this currently carried by a mobile?
if (m_RewardItem.RootParent != null && m_RewardItem.RootParent is Mobile)
{
// if so then remove it
((Mobile)(m_RewardItem.RootParent)).RemoveItem(m_RewardItem);
}
}
}
[CommandProperty(AccessLevel.GameMaster)]
public string TitleString
{
get { return m_TitleString; }
set { m_TitleString = value; InvalidateProperties(); }
}
[CommandProperty(AccessLevel.GameMaster)]
public string RewardString
{
get { return m_RewardString; }
set { m_RewardString = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string AttachmentString
{
get { return m_AttachmentString; }
set { m_AttachmentString = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string ConfigFile
{
get { return m_ConfigFile; }
set { m_ConfigFile = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public bool LoadConfig
{
get { return false; }
set { if (value == true) LoadXmlConfig(ConfigFile); }
}
[CommandProperty(AccessLevel.GameMaster)]
public bool PartyEnabled
{
get { return m_PartyEnabled; }
set { m_PartyEnabled = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public int PartyRange
{
get { return m_PartyRange; }
set { m_PartyRange = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string State1
{
get { return m_State1; }
set { m_State1 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string State2
{
get { return m_State2; }
set { m_State2 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string State3
{
get { return m_State3; }
set { m_State3 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string State4
{
get { return m_State4; }
set { m_State4 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string State5
{
get { return m_State5; }
set { m_State5 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string Description1
{
get { return m_Description1; }
set { m_Description1 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string Description2
{
get { return m_Description2; }
set { m_Description2 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string Description3
{
get { return m_Description3; }
set { m_Description3 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string Description4
{
get { return m_Description4; }
set { m_Description4 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string Description5
{
get { return m_Description5; }
set { m_Description5 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string Objective1
{
get { return m_Objective1; }
set { m_Objective1 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string Objective2
{
get { return m_Objective2; }
set { m_Objective2 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string Objective3
{
get { return m_Objective3; }
set { m_Objective3 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string Objective4
{
get { return m_Objective4; }
set { m_Objective4 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string Objective5
{
get { return m_Objective5; }
set { m_Objective5 = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public bool Completed1
{
get { return m_Completed1; }
set
{
m_Completed1 = value;
CheckAutoReward();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public bool Completed2
{
get { return m_Completed2; }
set
{
m_Completed2 = value;
CheckAutoReward();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public bool Completed3
{
get { return m_Completed3; }
set
{
m_Completed3 = value;
CheckAutoReward();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public bool Completed4
{
get { return m_Completed4; }
set
{
m_Completed4 = value;
CheckAutoReward();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public bool Completed5
{
get { return m_Completed5; }
set
{
m_Completed5 = value;
CheckAutoReward();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public string Status
{
get { return m_status_str; }
set { m_status_str = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool WasMoved
{
get { return m_wasMoved; }
set { m_wasMoved = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public DateTime TimeCreated
{
get { return m_TimeCreated; }
set { m_TimeCreated = value; }
}
[CommandProperty(AccessLevel.GameMaster)]
public double Expiration
{
get
{
return m_ExpirationDuration;
}
set
{
// cap the max value at 100 years
if (value > 876000)
{
m_ExpirationDuration = 876000;
}
else
{
m_ExpirationDuration = value;
}
}
}
[CommandProperty(AccessLevel.GameMaster)]
public TimeSpan ExpiresIn
{
get
{
if (m_ExpirationDuration > 0)
{
// if this is a player created quest, then refresh the expiration time until it is in someone elses possession
/*
if(PlayerMade && ((Owner == Creator) || (Owner == null)))
{
m_TimeCreated = DateTime.UtcNow;
}
*/
return (m_TimeCreated + TimeSpan.FromHours(m_ExpirationDuration) - DateTime.UtcNow);
}
else
{
return TimeSpan.FromHours(0);
}
}
}
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool IsExpired
{
get
{
if (((m_ExpirationDuration > 0) && (ExpiresIn <= TimeSpan.FromHours(0))))
{
return true;
}
else
return false;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool Repeatable
{
get
{
return m_Repeatable;
}
set
{
m_Repeatable = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public virtual TimeSpan NextRepeatable
{
get
{
return m_NextRepeatable;
}
set
{
m_NextRepeatable = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool AlreadyDone
{
get
{
// look for a quest attachment with the current quest name
if (XmlAttach.FindAttachment(Owner, typeof(XmlQuestAttachment), Name) == null)
return false;
return true;
}
}
public virtual string ExpirationString
{
get
{
if (AlreadyDone)
{
return "Already done";
}
else
if (m_ExpirationDuration <= 0)
{
return "Never expires";
}
else
if (IsExpired)
{
return "Expired";
}
else
{
TimeSpan ts = ExpiresIn;
int days = (int)ts.TotalDays;
int hours = (int)(ts - TimeSpan.FromDays(days)).TotalHours;
int minutes = (int)(ts - TimeSpan.FromHours(hours)).TotalMinutes;
int seconds = (int)(ts - TimeSpan.FromMinutes(minutes)).TotalSeconds;
if (days > 0)
{
return String.Format("Expires in {0} days {1} hrs", days, hours);
}
else
if (hours > 0)
{
return String.Format("Expires in {0} hrs {1} mins", hours, minutes);
}
else
{
return String.Format("Expires in {0} mins {1} secs", minutes, seconds);
}
}
}
}
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool IsValid
{
get
{
if (WasMoved || IsExpired)
{
// eliminate reward definitions
RewardString = null;
AttachmentString = null;
// return any reward items
ReturnReward();
// and get rid of the pack
if (Pack != null)
Pack.Delete();
return false;
}
else
if (AlreadyDone)
{
return false;
}
else
return true;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool IsCompleted
{
get
{
if (IsValid &&
(Completed1 || Objective1 == null || (Objective1.Length == 0)) &&
(Completed2 || Objective2 == null || (Objective2.Length == 0)) &&
(Completed3 || Objective3 == null || (Objective3.Length == 0)) &&
(Completed4 || Objective4 == null || (Objective4.Length == 0)) &&
(Completed5 || Objective5 == null || (Objective5.Length == 0))
)
return true;
else
return false;
}
}
public bool HandlesOnSkillUse { get { return (IsValid && m_SkillTrigger != null && m_SkillTrigger.Length > 0); } }
public void OnSkillUse(Mobile m, Skill skill, bool success)
{
}
private void CheckOwnerFlag()
{
if (Owner != null && !Owner.Deleted)
{
// need to check to see if any other questtoken items are owned
// search the Owners top level pack for an xmlquesttoken
List<Item> list = XmlQuest.FindXmlQuest(Owner);
if (list == null || list.Count == 0)
{
// if none remain then flag the ower as having none
Owner.SetFlag(XmlQuest.CarriedXmlQuestFlag, false);
}
}
}
public virtual void Invalidate()
{
//Hue = 32;
//LootType = LootType.Regular;
if (Owner != null)
{
Owner.SendMessage(String.Format("Quest invalidated - '{0}' removed", Name));
}
this.Delete();
}
public void CheckRewardItem()
{
// go through all reward items and delete anything that is movable. This blocks any exploits where players might
// try to add items themselves
if (m_RewardItem != null && !m_RewardItem.Deleted && m_RewardItem is Container)
{
foreach (Item i in ((Container)m_RewardItem).FindItemsByType(typeof(Item), true))
{
if (i.Movable)
{
i.Delete();
}
}
}
}
public void CheckAutoReward()
{
if (!this.Deleted && AutoReward && IsCompleted && Owner != null &&
((RewardItem != null && !m_RewardItem.Deleted) || (RewardAttachment != null && !m_RewardAttachment.Deleted)))
{
if (RewardItem != null)
{
// make sure nothing has been added to the pack other than the original reward items
CheckRewardItem();
m_RewardItem.Movable = true;
if (m_Pack != null)
{
// make sure all of the items in the pack are movable as well
PackItemsMovable(m_Pack, true);
}
//RefreshPackLocation(Owner, false);
Owner.AddToBackpack(m_RewardItem);
//AddMobileWeight(Owner,m_RewardItem);
m_RewardItem = null;
}
if (RewardAttachment != null)
{
Timer.DelayCall(TimeSpan.Zero, new TimerStateCallback(AttachToCallback), new object[] { Owner, m_RewardAttachment });
m_RewardAttachment = null;
}
Owner.SendMessage(String.Format("{0} completed. You receive the quest reward!", Name));
this.Delete();
}
}
public void AttachToCallback(object state)
{
object[] args = (object[])state;
XmlAttach.AttachTo(args[0], (XmlAttachment)args[1]);
}
private const string XmlTableName = "Properties";
private const string XmlDataSetName = "XmlQuestToken";
public void LoadXmlConfig(string filename)
{
if (filename == null || filename.Length <= 0) return;
// Check if the file exists
if (System.IO.File.Exists(filename) == true)
{
FileStream fs = null;
try
{
fs = File.Open(filename, FileMode.Open, FileAccess.Read);
}
catch { }
if (fs == null)
{
Status = String.Format("Unable to open {0} for loading", filename);
return;
}
// Create the data set
DataSet ds = new DataSet(XmlDataSetName);
// Read in the file
//ds.ReadXml( e.Arguments[0].ToString() );
bool fileerror = false;
try
{
ds.ReadXml(fs);
}
catch { fileerror = true; }
// close the file
fs.Close();
if (fileerror)
{
Console.WriteLine("XmlQuestToken: Error in XML config file '{0}'", filename);
return;
}
// Check that at least a single table was loaded
if (ds.Tables != null && ds.Tables.Count > 0)
{
if (ds.Tables[XmlTableName] != null && ds.Tables[XmlTableName].Rows.Count > 0)
{
foreach (DataRow dr in ds.Tables[XmlTableName].Rows)
{
bool valid_entry;
string strEntry = null;
bool boolEntry = true;
double doubleEntry = 0;
int intEntry = 0;
TimeSpan timespanEntry = TimeSpan.Zero;
valid_entry = true;
try { strEntry = (string)dr["Name"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.Name = strEntry;
}
valid_entry = true;
strEntry = null;
try { strEntry = (string)dr["Title"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.TitleString = strEntry;
}
valid_entry = true;
strEntry = null;
try { strEntry = (string)dr["Note"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.NoteString = strEntry;
}
valid_entry = true;
strEntry = null;
try { strEntry = (string)dr["Reward"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.RewardString = strEntry;
}
valid_entry = true;
strEntry = null;
try { strEntry = (string)dr["Attachment"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.AttachmentString = strEntry;
}
valid_entry = true;
strEntry = null;
try { strEntry = (string)dr["Objective1"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.Objective1 = strEntry;
}
valid_entry = true;
strEntry = null;
try { strEntry = (string)dr["Objective2"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.Objective2 = strEntry;
}
valid_entry = true;
strEntry = null;
try { strEntry = (string)dr["Objective3"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.Objective3 = strEntry;
}
valid_entry = true;
strEntry = null;
try { strEntry = (string)dr["Objective4"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.Objective4 = strEntry;
}
valid_entry = true;
strEntry = null;
try { strEntry = (string)dr["Objective5"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.Objective5 = strEntry;
}
valid_entry = true;
strEntry = null;
try { strEntry = (string)dr["Description1"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.Description1 = strEntry;
}
valid_entry = true;
strEntry = null;
try { strEntry = (string)dr["Description2"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.Description2 = strEntry;
}
valid_entry = true;
strEntry = null;
try { strEntry = (string)dr["Description3"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.Description3 = strEntry;
}
valid_entry = true;
strEntry = null;
try { strEntry = (string)dr["Description4"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.Description4 = strEntry;
}
valid_entry = true;
strEntry = null;
try { strEntry = (string)dr["Description5"]; }
catch { valid_entry = false; }
if (valid_entry)
{
this.Description5 = strEntry;
}
valid_entry = true;
boolEntry = false;
try { boolEntry = bool.Parse((string)dr["PartyEnabled"]); }
catch { valid_entry = false; }
if (valid_entry)
{
this.PartyEnabled = boolEntry;
}
valid_entry = true;
boolEntry = false;
try { boolEntry = bool.Parse((string)dr["AutoReward"]); }
catch { valid_entry = false; }
if (valid_entry)
{
this.AutoReward = boolEntry;
}
valid_entry = true;
boolEntry = true;
try { boolEntry = bool.Parse((string)dr["CanSeeReward"]); }
catch { valid_entry = false; }
if (valid_entry)
{
this.CanSeeReward = boolEntry;
}
valid_entry = true;
boolEntry = true;
try { boolEntry = bool.Parse((string)dr["Repeatable"]); }
catch { valid_entry = false; }
if (valid_entry)
{
this.m_Repeatable = boolEntry;
}
valid_entry = true;
timespanEntry = TimeSpan.Zero;
try { timespanEntry = TimeSpan.Parse((string)dr["NextRepeatable"]); }
catch { valid_entry = false; }
if (valid_entry)
{
this.m_NextRepeatable = timespanEntry;
}
valid_entry = true;
boolEntry = false;
try { boolEntry = bool.Parse((string)dr["PlayerMade"]); }
catch { valid_entry = false; }
if (valid_entry)
{
this.PlayerMade = boolEntry;
}
valid_entry = true;
intEntry = 0;
try { intEntry = int.Parse((string)dr["PartyRange"]); }
catch { valid_entry = false; }
if (valid_entry)
{
this.PartyRange = intEntry;
}
valid_entry = true;
doubleEntry = 0;
try { doubleEntry = double.Parse((string)dr["Expiration"]); }
catch { valid_entry = false; }
if (valid_entry)
{
this.Expiration = doubleEntry;
}
}
}
}
}
}
}
}