451 lines
13 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |