Files
abysmal-isle/Scripts/Services/XmlSpawner/XmlSpawner Core/XmlAttachments/XmlUse.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

492 lines
17 KiB
C#

using System;
using Server;
using Server.Items;
using Server.Network;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Engines.XmlSpawner2
{
public class XmlUse : XmlAttachment
{
private bool m_BlockDefaultUse;
private string m_Condition; // additional condition required for use
private string m_TargetingAction; // action performed when the target cursor is brought up
private string m_TargetCondition; // condition test applied when target is selected to determine whether it is appropriate
private string m_TargetFailureAction; // action performed if target condition is not met
private string m_SuccessAction; // action performed on successful use or targeting
private string m_FailureAction; // action performed if the player cannot use the object for reasons other than range, refractory, or maxuses
private string m_RefractoryAction; // action performed if the object is used before the refractory interval expires
private string m_MaxUsesAction; // action performed if the object is used when the maxuses are exceeded
private int m_NUses = 0;
private int m_MaxRange = 3; // must be within 3 tiles to use by default
private int m_MaxTargetRange = 30; // must be within 30 tiles to target by default
private int m_MaxUses = 0;
private TimeSpan m_Refractory = TimeSpan.Zero;
public DateTime m_EndTime;
private bool m_RequireLOS = false;
private bool m_AllowCarried = true;
private bool m_TargetingEnabled = false;
[CommandProperty(AccessLevel.GameMaster)]
public bool TargetingEnabled { get { return m_TargetingEnabled; } set { m_TargetingEnabled = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public bool AllowCarried { get { return m_AllowCarried; } set { m_AllowCarried = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public bool RequireLOS { get { return m_RequireLOS; } set { m_RequireLOS = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public int MaxRange { get { return m_MaxRange; } set { m_MaxRange = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public int MaxTargetRange { get { return m_MaxTargetRange; } set { m_MaxTargetRange = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public int NUses { get { return m_NUses; } set { m_NUses = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public int MaxUses { get { return m_MaxUses; } set { m_MaxUses = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public TimeSpan Refractory { get { return m_Refractory; } set { m_Refractory = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public bool BlockDefaultUse { get { return m_BlockDefaultUse; } set { m_BlockDefaultUse = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public string Condition { get { return m_Condition; } set { m_Condition = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public string TargetCondition { get { return m_TargetCondition; } set { m_TargetCondition = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public string TargetingAction { get { return m_TargetingAction; } set { m_TargetingAction = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public string TargetFailureAction { get { return m_TargetFailureAction; } set { m_TargetFailureAction = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public string SuccessAction { get { return m_SuccessAction; } set { m_SuccessAction = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public string FailureAction { get { return m_FailureAction; } set { m_FailureAction = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public string RefractoryAction { get { return m_RefractoryAction; } set { m_RefractoryAction = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public string MaxUsesAction { get { return m_MaxUsesAction; } set { m_MaxUsesAction = value; } }
public XmlUse(ASerial serial)
: base(serial)
{
}
[Attachable]
public XmlUse()
{
}
[Attachable]
public XmlUse(int maxuses)
{
MaxUses = maxuses;
}
[Attachable]
public XmlUse(int maxuses, double refractory)
{
MaxUses = maxuses;
Refractory = TimeSpan.FromSeconds(refractory);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)3);
// version 3
writer.Write(m_MaxTargetRange);
// version 2
writer.Write(m_TargetingEnabled);
writer.Write(m_TargetingAction);
writer.Write(m_TargetCondition);
writer.Write(m_TargetFailureAction);
// version 1
writer.Write(m_AllowCarried);
// version 0
writer.Write(m_RequireLOS);
writer.Write(m_MaxRange);
writer.Write(m_Refractory);
writer.Write(m_EndTime - DateTime.UtcNow);
writer.Write(m_MaxUses);
writer.Write(m_NUses);
writer.Write(m_BlockDefaultUse);
writer.Write(m_Condition);
writer.Write(m_SuccessAction);
writer.Write(m_FailureAction);
writer.Write(m_RefractoryAction);
writer.Write(m_MaxUsesAction);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 3:
m_MaxTargetRange = reader.ReadInt();
goto case 2;
case 2:
m_TargetingEnabled = reader.ReadBool();
m_TargetingAction = reader.ReadString();
m_TargetCondition = reader.ReadString();
m_TargetFailureAction = reader.ReadString();
goto case 1;
case 1:
m_AllowCarried = reader.ReadBool();
goto case 0;
case 0:
// version 0
m_RequireLOS = reader.ReadBool();
m_MaxRange = reader.ReadInt();
Refractory = reader.ReadTimeSpan();
TimeSpan remaining = reader.ReadTimeSpan();
m_EndTime = DateTime.UtcNow + remaining;
m_MaxUses = reader.ReadInt();
m_NUses = reader.ReadInt();
m_BlockDefaultUse = reader.ReadBool();
m_Condition = reader.ReadString();
m_SuccessAction = reader.ReadString();
m_FailureAction = reader.ReadString();
m_RefractoryAction = reader.ReadString();
m_MaxUsesAction = reader.ReadString();
break;
}
}
public void ExecuteActions(Mobile mob, object target, string actions)
{
if (actions == null || actions.Length <= 0) return;
// execute any action associated with it
// allow for multiple action strings on a single line separated by a semicolon
string[] args = actions.Split(';');
for (int j = 0; j < args.Length; j++)
{
ExecuteAction(mob, target, args[j]);
}
}
private void ExecuteAction(Mobile mob, object target, string action)
{
if (action == null || action.Length <= 0) return;
string status_str = null;
Server.Mobiles.XmlSpawner.SpawnObject TheSpawn = new Server.Mobiles.XmlSpawner.SpawnObject(null, 0);
TheSpawn.TypeName = action;
string substitutedtypeName = BaseXmlSpawner.ApplySubstitution(null, target, mob, action);
string typeName = BaseXmlSpawner.ParseObjectType(substitutedtypeName);
Point3D loc = new Point3D(0, 0, 0);
Map map = null;
if (target is Item)
{
Item ti = target as Item;
if (ti.Parent == null)
{
loc = ti.Location;
map = ti.Map;
}
else if (ti.RootParent is Item)
{
loc = ((Item)ti.RootParent).Location;
map = ((Item)ti.RootParent).Map;
}
else if (ti.RootParent is Mobile)
{
loc = ((Mobile)ti.RootParent).Location;
map = ((Mobile)ti.RootParent).Map;
}
}
else if (target is Mobile)
{
Mobile ti = target as Mobile;
loc = ti.Location;
map = ti.Map;
}
if (BaseXmlSpawner.IsTypeOrItemKeyword(typeName))
{
BaseXmlSpawner.SpawnTypeKeyword(target, TheSpawn, typeName, substitutedtypeName, true, mob, loc, map, out status_str);
}
else
{
// its a regular type descriptor so find out what it is
Type type = SpawnerType.GetType(typeName);
try
{
string[] arglist = BaseXmlSpawner.ParseString(substitutedtypeName, 3, "/");
object o = Server.Mobiles.XmlSpawner.CreateObject(type, arglist[0]);
if (o == null)
{
status_str = "invalid type specification: " + arglist[0];
}
else
if (o is Mobile)
{
Mobile m = (Mobile)o;
if (m is BaseCreature)
{
BaseCreature c = (BaseCreature)m;
c.Home = loc; // Spawners location is the home point
}
m.Location = loc;
m.Map = map;
BaseXmlSpawner.ApplyObjectStringProperties(null, substitutedtypeName, m, mob, target, out status_str);
}
else
if (o is Item)
{
Item item = (Item)o;
BaseXmlSpawner.AddSpawnItem(null, target, TheSpawn, item, loc, map, mob, false, substitutedtypeName, out status_str);
}
}
catch { }
}
ReportError(mob, status_str);
}
private void ReportError(Mobile mob, string status_str)
{
if (status_str != null && mob != null && !mob.Deleted && mob is PlayerMobile && mob.AccessLevel > AccessLevel.Player)
{
mob.SendMessage(33, String.Format("{0}:{1}", Name, status_str));
}
}
// return true to allow use
private bool CheckCondition(Mobile from, object target)
{
// test the condition if there is one
if (Condition != null && Condition.Length > 0)
{
string status_str;
return BaseXmlSpawner.CheckPropertyString(null, target, Condition, from, out status_str);
}
return true;
}
// return true to allow use
private bool CheckTargetCondition(Mobile from, object target)
{
// test the condition if there is one
if (TargetCondition != null && TargetCondition.Length > 0)
{
string status_str;
return BaseXmlSpawner.CheckPropertyString(null, target, TargetCondition, from, out status_str);
}
return true;
}
// return true to allow use
private bool CheckRange(Mobile from, object target)
{
if (from == null || !(target is IEntity) || MaxRange < 0) return false;
Map map = ((IEntity)target).Map;
Point3D loc = ((IEntity)target).Location;
if (map != from.Map) return false;
// check for allowed use in pack
if (target is Item)
{
Item targetitem = (Item)target;
// is it carried by the user?
if (targetitem.RootParent == from)
{
return AllowCarried;
}
else
// block use in other containers or on other mobiles
if (targetitem.Parent != null)
{
return false;
}
}
bool haslos = true;
if (RequireLOS)
{
// check los as well
haslos = from.InLOS(target);
}
return from.InRange(loc, MaxRange) && haslos;
}
public bool CheckMaxUses
{
get
{
// is there a use limit?
if (MaxUses > 0 && NUses >= MaxUses) return false;
return true;
}
}
public bool CheckRefractory
{
get
{
// is there a refractory limit?
// if it is still refractory then return
if (Refractory > TimeSpan.Zero && DateTime.UtcNow < m_EndTime) return false;
return true;
}
}
public void OutOfRange(Mobile from)
{
if (from == null) return;
from.SendLocalizedMessage(500446); // That is too far away.
}
public class XmlUseTarget : Target
{
private object m_objectused;
private XmlUse m_xa;
public XmlUseTarget(int range, object objectused, XmlUse xa)
: base(range, true, TargetFlags.None)
{
m_objectused = objectused;
m_xa = xa;
CheckLOS = false;
}
protected override void OnTarget(Mobile from, object targeted)
{
if (from == null || targeted == null || m_xa == null) return;
// success
if (m_xa.CheckTargetCondition(from, targeted))
{
m_xa.ExecuteActions(from, targeted, m_xa.SuccessAction);
m_xa.m_EndTime = DateTime.UtcNow + m_xa.Refractory;
m_xa.NUses++;
}
else
{
m_xa.ExecuteActions(from, targeted, m_xa.TargetFailureAction);
}
}
}
private void TryToTarget(Mobile from, object target, XmlUse xa)
{
if (from == null) return;
ExecuteActions(from, target, TargetingAction);
if (xa != null)
{
from.Target = new XmlUseTarget(xa.MaxTargetRange, target, xa);
}
}
private void TryToUse(Mobile from, object target)
{
if (CheckRange(from, target) && CheckCondition(from, target) && CheckMaxUses && CheckRefractory)
{
// check for targeting
if (TargetingEnabled)
{
TryToTarget(from, target, this);
}
else
{
// success
ExecuteActions(from, target, SuccessAction);
m_EndTime = DateTime.UtcNow + Refractory;
NUses++;
}
}
else
{
// failure
if (!CheckRange(from, target))
{
OutOfRange(from);
}
else if (!CheckRefractory)
{
ExecuteActions(from, target, RefractoryAction);
}
else if (!CheckMaxUses)
{
ExecuteActions(from, target, MaxUsesAction);
}
else
{
ExecuteActions(from, target, FailureAction);
}
}
}
// disable the default use of the target
public override bool BlockDefaultOnUse(Mobile from, object target)
{
return (BlockDefaultUse || !(CheckRange(from, target) && CheckCondition(from, target) && CheckMaxUses && CheckRefractory));
}
// this is called when the attachment is on the user
public override void OnUser(object target)
{
Mobile from = AttachedTo as Mobile;
TryToUse(from, target);
}
// this is called when the attachment is on the target being used
public override void OnUse(Mobile from)
{
object target = AttachedTo;
// if a target tries to use itself, then ignore it, it will be handled by OnUser
if (target == from) return;
TryToUse(from, target);
}
}
}