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

451 lines
13 KiB
C#

using System;
namespace Server.Engines.XmlSpawner2
{
public class XmlAnimate : XmlAttachment
{
private int m_AnimationValue = 0;// default animation
private int m_FrameCount = 7;// default framecount
private int m_RepeatCount = 1;// default repeatcount
private int m_AnimationDelay = 0;// default animation delay
private bool m_Repeat = false;// default repeat
private bool m_Forward = true;// default animation direction
private string m_ActivationWord = null;// no word activation by default
private TimeSpan m_Refractory = TimeSpan.FromSeconds(5);// 5 seconds default time between activations
private DateTime m_EndTime;
private int m_ProximityRange = 5;// default movement activation from 5 tiles away
private LoopTimer m_Timer;
private int m_LoopCount = 0;// repeat animations using a timed loop
private int m_LoopDelay = 5;// interval in seconds between loop ticks
private int m_CurrentCount = 0;
// a serial constructor is REQUIRED
public XmlAnimate(ASerial serial)
: base(serial)
{
}
[Attachable]
public XmlAnimate()
{
}
[Attachable]
public XmlAnimate(int animation)
{
this.AnimationValue = animation;
}
[Attachable]
public XmlAnimate(int animation, double refractory)
{
this.AnimationValue = animation;
this.Refractory = TimeSpan.FromSeconds(refractory);
}
[Attachable]
public XmlAnimate(int animation, int framecount, double refractory)
{
this.AnimationValue = animation;
this.FrameCount = framecount;
this.Refractory = TimeSpan.FromSeconds(refractory);
}
[Attachable]
public XmlAnimate(int animation, double refractory, int loopcount, int loopdelay)
{
this.LoopCount = loopcount;
this.LoopDelay = loopdelay;
this.AnimationValue = animation;
this.Refractory = TimeSpan.FromSeconds(refractory);
}
[Attachable]
public XmlAnimate(int animation, int framecount, double refractory, int loopcount, int loopdelay)
{
this.LoopCount = loopcount;
this.LoopDelay = loopdelay;
this.AnimationValue = animation;
this.FrameCount = framecount;
this.Refractory = TimeSpan.FromSeconds(refractory);
}
[CommandProperty(AccessLevel.GameMaster)]
public int ProximityRange
{
get
{
return this.m_ProximityRange;
}
set
{
this.m_ProximityRange = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int FrameCount
{
get
{
return this.m_FrameCount;
}
set
{
this.m_FrameCount = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int RepeatCount
{
get
{
return this.m_RepeatCount;
}
set
{
this.m_RepeatCount = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int AnimationDelay
{
get
{
return this.m_AnimationDelay;
}
set
{
this.m_AnimationDelay = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public bool Repeat
{
get
{
return this.m_Repeat;
}
set
{
this.m_Repeat = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public bool Forward
{
get
{
return this.m_Forward;
}
set
{
this.m_Forward = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int AnimationValue
{
get
{
return this.m_AnimationValue;
}
set
{
this.m_AnimationValue = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public string ActivationWord
{
get
{
return this.m_ActivationWord;
}
set
{
this.m_ActivationWord = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public TimeSpan Refractory
{
get
{
return this.m_Refractory;
}
set
{
this.m_Refractory = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int LoopCount
{
get
{
return this.m_LoopCount;
}
set
{
this.m_LoopCount = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int LoopDelay
{
get
{
return this.m_LoopDelay;
}
set
{
this.m_LoopDelay = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int CurrentCount
{
get
{
return this.m_CurrentCount;
}
set
{
this.m_CurrentCount = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public bool DoAnimate
{
get
{
return false;
}
set
{
if (value == true)
this.OnTrigger(null, null);
}
}
[CommandProperty(AccessLevel.GameMaster)]
public bool DoReset
{
get
{
return false;
}
set
{
if (value == true)
this.Reset();
}
}
// These are the various ways in which the message attachment can be constructed.
// These can be called via the [addatt interface, via scripts, via the spawner ATTACH keyword.
// Other overloads could be defined to handle other types of arguments
public override bool HandlesOnSpeech
{
get
{
return (this.ActivationWord != null);
}
}
public override bool HandlesOnMovement
{
get
{
return (this.ProximityRange >= 0 && this.ActivationWord == null);
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
// version 0
writer.Write(this.m_CurrentCount);
writer.Write(this.m_LoopCount);
writer.Write(this.m_LoopDelay);
writer.Write(this.m_ProximityRange);
writer.Write(this.m_AnimationValue);
writer.Write(this.m_FrameCount);
writer.Write(this.m_RepeatCount);
writer.Write(this.m_AnimationDelay);
writer.Write(this.m_Forward);
writer.Write(this.m_Repeat);
writer.Write(this.m_ActivationWord);
writer.Write(this.m_Refractory);
writer.Write(this.m_EndTime - DateTime.UtcNow);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
// version 0
this.m_CurrentCount = reader.ReadInt();
this.m_LoopCount = reader.ReadInt();
this.m_LoopDelay = reader.ReadInt();
this.m_ProximityRange = reader.ReadInt();
this.m_AnimationValue = reader.ReadInt();
this.m_FrameCount = reader.ReadInt();
this.m_RepeatCount = reader.ReadInt();
this.m_AnimationDelay = reader.ReadInt();
this.m_Forward = reader.ReadBool();
this.m_Repeat = reader.ReadBool();
this.m_ActivationWord = reader.ReadString();
this.m_Refractory = reader.ReadTimeSpan();
TimeSpan remaining = reader.ReadTimeSpan();
this.m_EndTime = DateTime.UtcNow + remaining;
break;
}
// restart any animation loops that were active
if (this.CurrentCount > 0)
{
this.DoTimer(TimeSpan.FromSeconds(this.LoopDelay));
}
}
public override string OnIdentify(Mobile from)
{
if (from == null || from.AccessLevel < AccessLevel.Counselor)
return null;
string msg = String.Format("Animation #{0},{1} : {2} secs between uses", this.AnimationValue, this.FrameCount, this.Refractory.TotalSeconds);
if (this.ActivationWord == null)
{
return msg;
}
else
{
return String.Format("{0} : trigger on '{1}'", msg, this.ActivationWord);
}
}
public override void OnSpeech(SpeechEventArgs e)
{
base.OnSpeech(e);
if (e.Mobile == null || e.Mobile.AccessLevel > AccessLevel.Player)
return;
if (e.Speech == this.ActivationWord)
{
this.OnTrigger(null, e.Mobile);
}
}
public override void OnMovement(MovementEventArgs e)
{
base.OnMovement(e);
if (e.Mobile == null || e.Mobile.AccessLevel > AccessLevel.Player)
return;
if (this.AttachedTo is Item && (((Item)this.AttachedTo).Parent == null) && Utility.InRange(e.Mobile.Location, ((Item)this.AttachedTo).Location, this.ProximityRange))
{
this.OnTrigger(null, e.Mobile);
}
else
return;
}
public override void OnAttach()
{
base.OnAttach();
// only attach to mobiles
if (!(this.AttachedTo is Mobile))
{
this.Delete();
}
}
public void Reset()
{
if (this.m_Timer != null)
this.m_Timer.Stop();
this.CurrentCount = 0;
this.m_EndTime = DateTime.UtcNow;
}
public void Animate()
{
// play a animation
if (this.AttachedTo is Mobile && this.AnimationValue >= 0)
{
((Mobile)this.AttachedTo).Animate(this.AnimationValue, this.FrameCount, this.RepeatCount, this.Forward, this.Repeat, this.AnimationDelay);
}
this.UpdateRefractory();
this.CurrentCount--;
}
public void UpdateRefractory()
{
this.m_EndTime = DateTime.UtcNow + this.Refractory;
}
public override void OnTrigger(object activator, Mobile m)
{
if (DateTime.UtcNow < this.m_EndTime)
return;
if (this.LoopCount > 0)
{
this.CurrentCount = this.LoopCount;
// check to make sure the timer is running
this.DoTimer(TimeSpan.FromSeconds(this.LoopDelay));
}
else
{
this.Animate();
}
}
private void DoTimer(TimeSpan delay)
{
if (this.m_Timer != null)
this.m_Timer.Stop();
this.m_Timer = new LoopTimer(this, delay);
this.m_Timer.Start();
}
private class LoopTimer : Timer
{
public readonly TimeSpan m_delay;
private readonly XmlAnimate m_attachment;
public LoopTimer(XmlAnimate attachment, TimeSpan delay)
: base(delay, delay)
{
this.Priority = TimerPriority.OneSecond;
this.m_attachment = attachment;
this.m_delay = delay;
}
protected override void OnTick()
{
if (this.m_attachment != null && !this.m_attachment.Deleted)
{
this.m_attachment.Animate();
if (this.m_attachment.CurrentCount <= 0)
this.Stop();
}
else
{
this.Stop();
}
}
}
}
}