Overwrite

Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
Unstable Kitsune
2023-11-28 23:20:26 -05:00
parent 3cd54811de
commit b918192e4e
11608 changed files with 2644205 additions and 47 deletions

View File

@@ -0,0 +1,363 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Server;
#endregion
namespace VitaNex.FX
{
public static class EffectUtility
{
public static readonly Point3D[][] EmptyPoints = new Point3D[0][];
}
public interface IEffect
{
IPoint3D Start { get; set; }
Map Map { get; set; }
Action Callback { get; set; }
bool Sending { get; }
void Send();
}
public abstract class BaseEffect<TQueue, TEffectInfo> : List<TQueue>, IEffect
where TQueue : EffectQueue<TEffectInfo>
where TEffectInfo : EffectInfo
{
public bool Processing { get; protected set; }
public int CurrentProcess { get; protected set; }
public TQueue CurrentQueue { get; private set; }
public bool Sending { get; protected set; }
public virtual IPoint3D Start { get; set; }
public virtual Map Map { get; set; }
public virtual int Repeat { get; set; }
public virtual TimeSpan Interval { get; set; }
public virtual Action<TEffectInfo> EffectHandler { get; set; }
public virtual Action<TEffectInfo> EffectMutator { get; set; }
public virtual Action Callback { get; set; }
public virtual bool EnableMutate { get; set; }
public virtual bool Reversed { get; set; }
public abstract TEffectInfo[] Effects { get; }
public BaseEffect(
IPoint3D start,
Map map,
int repeat = 0,
TimeSpan? interval = null,
Action<TEffectInfo> effectHandler = null,
Action callback = null)
{
Start = start;
Map = map;
Repeat = Math.Max(0, repeat);
Interval = interval ?? TimeSpan.FromMilliseconds(100);
EffectHandler = effectHandler;
Callback = callback;
}
public abstract TQueue CreateEffectQueue(IEnumerable<TEffectInfo> queue);
public abstract TEffectInfo CloneEffectInfo(TEffectInfo src);
public void Update()
{
this.Free(true);
if (Effects == null || Effects.Length == 0)
{
return;
}
var points = GetTargetPoints(CurrentProcess);
if (points == null || points.Length == 0)
{
return;
}
Capacity = points.Length;
this.SetAll(i => null);
for (var i = 0; i < points.Length; i++)
{
var list = points[i];
if (list == null || list.Length == 0)
{
continue;
}
var fx = new TEffectInfo[list.Length][];
fx.SetAll(fxi => new TEffectInfo[Effects.Length]);
Parallel.For(
0,
list.Length,
index =>
{
var p = list[index];
var pIndex = 0;
for (var ei = 0; ei < Effects.Length; ei++)
{
var e = CloneEffectInfo(Effects[ei]);
if (e == null || e.IsDisposed)
{
continue;
}
e.QueueIndex = index;
e.ProcessIndex = pIndex++;
e.Source = new Entity(Serial.Zero, p, Map);
e.Map = Map;
if (EnableMutate)
{
MutateEffect(e);
}
if (!e.IsDisposed)
{
fx[index][ei] = e;
}
}
});
var q = CreateEffectQueue(fx.Combine());
if (q.Mutator == null && EffectMutator != null)
{
q.Mutator = EffectMutator;
}
if (q.Handler == null && EffectHandler != null)
{
q.Handler = EffectHandler;
}
this[i] = q;
}
RemoveAll(l => l == null);
this.Free(false);
if (Reversed)
{
Reverse();
}
var idx = 0;
foreach (var cur in this)
{
if (++idx >= Count)
{
cur.Callback = InternalCallback;
break;
}
var next = this[idx];
cur.Callback = () => InternalCallback(next);
}
OnUpdated();
}
public virtual Point3D[][] GetTargetPoints(int dist)
{
return Start == null ? EffectUtility.EmptyPoints : new[] { new[] { Start.Clone3D() } };
}
protected virtual void OnUpdated()
{ }
public virtual void MutateEffect(TEffectInfo e)
{ }
public void Send()
{
if (Sending)
{
return;
}
Sending = true;
VitaNexCore.TryCatch(InternalSend, VitaNexCore.ToConsole);
}
public virtual void OnSend()
{ }
private void InternalSend()
{
Update();
if (Count == 0 || this[0] == null)
{
return;
}
Processing = true;
InternalMoveNext(this[0]);
OnSend();
}
private void InternalMoveNext(TQueue next)
{
CurrentQueue = next;
CurrentQueue.Process();
}
private void InternalCallback()
{
Sending = false;
if (Callback != null)
{
Callback();
}
if (++CurrentProcess <= Repeat)
{
if (Interval <= TimeSpan.Zero)
{
Send();
return;
}
Timer.DelayCall(Interval, Send);
return;
}
CurrentProcess = 0;
Processing = false;
this.Free(true);
}
private void InternalCallback(TQueue next)
{
Processing = true;
if (Interval <= TimeSpan.Zero)
{
InternalMoveNext(next);
return;
}
Timer.DelayCall(Interval, InternalMoveNext, next);
}
}
public abstract class BaseRangedEffect<TQueue, TEffectInfo> : BaseEffect<TQueue, TEffectInfo>
where TQueue : EffectQueue<TEffectInfo>
where TEffectInfo : EffectInfo
{
public virtual int Range { get; set; }
public virtual bool AverageZ { get; set; }
public virtual bool LOSCheck { get; set; }
public BaseRangedEffect(
IPoint3D start,
Map map,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<TEffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, repeat, interval, effectHandler, callback)
{
Range = range;
AverageZ = true;
LOSCheck = false;
}
public override Point3D[][] GetTargetPoints(int count)
{
return Start.ScanRangeGet(Map, Range, ComputePoint, AverageZ);
}
protected virtual bool ComputePoint(ScanRangeResult r)
{
if (!r.Excluded && ExcludePoint(r.Current, r.Distance, Utility.GetDirection(Start, r.Current)))
{
r.Exclude();
}
return false;
}
protected virtual bool ExcludePoint(Point3D p, int range, Direction fromCenter)
{
return LOSCheck && !Map.LineOfSight(p, Start);
}
}
public abstract class BaseBoundsEffect<TQueue, TEffectInfo> : BaseEffect<TQueue, TEffectInfo>
where TQueue : EffectQueue<TEffectInfo>
where TEffectInfo : EffectInfo
{
public virtual Rectangle2D Bounds { get; set; }
public virtual bool AverageZ { get; set; }
public BaseBoundsEffect(
IPoint3D start,
Map map,
Rectangle2D bounds,
int repeat = 0,
TimeSpan? interval = null,
Action<TEffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, repeat, interval, effectHandler, callback)
{
Bounds = bounds;
AverageZ = true;
}
public override Point3D[][] GetTargetPoints(int count)
{
var points = new List<Point3D>[Math.Max(Bounds.Width, Bounds.Height)];
Bounds.ForEach(
p2d =>
{
var distance = (int)Math.Floor(Start.GetDistance(p2d));
points[distance].Add(p2d.ToPoint3D(AverageZ ? p2d.GetAverageZ(Map) : Start.Z));
});
var arr = points.ToMultiArray();
points.Free(true);
return arr;
}
}
}

View File

@@ -0,0 +1,427 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Commands;
using VitaNex.Network;
#endregion
namespace VitaNex.FX
{
public enum ExplodeFX
{
None = 0,
Random,
Smoke,
Water,
Fire,
Earth,
Air,
Energy,
Poison
}
public static class ExplodeEffects
{
public static void Initialize()
{
CommandSystem.Register(
"ExplodeFXHide",
AccessLevel.GameMaster,
ce =>
{
if (ce == null || ce.Mobile == null)
{
return;
}
var m = ce.Mobile;
if (m.Hidden)
{
m.Hidden = false;
CommandSystem.Entries["ExplodeFX"].Handler(ce);
}
else
{
CommandSystem.Entries["ExplodeFX"].Handler(ce);
m.Hidden = true;
}
});
CommandSystem.Register(
"ExplodeFX",
AccessLevel.GameMaster,
ce =>
{
if (ce == null || ce.Mobile == null)
{
return;
}
var m = ce.Mobile;
if (ce.Arguments.Length < 1 || !Enum.TryParse(ce.Arguments[0], true, out ExplodeFX effect))
{
effect = ExplodeFX.None;
}
if (ce.Arguments.Length < 2 || !Int32.TryParse(ce.Arguments[1], out var range))
{
range = 5;
}
if (ce.Arguments.Length < 3 || !Int32.TryParse(ce.Arguments[2], out var speed))
{
speed = 10;
}
if (ce.Arguments.Length < 4 || !Int32.TryParse(ce.Arguments[3], out var repeat))
{
repeat = 0;
}
if (ce.Arguments.Length < 5 || !Int32.TryParse(ce.Arguments[4], out var reverse))
{
reverse = 0;
}
range = Math.Max(0, Math.Min(100, range));
speed = Math.Max(1, Math.Min(10, speed));
repeat = Math.Max(0, Math.Min(100, repeat));
reverse = Math.Max(0, Math.Min(1, reverse));
var e = effect.CreateInstance(
m.Location,
m.Map,
range,
repeat,
TimeSpan.FromMilliseconds(1000 - ((speed - 1) * 100)));
if (e != null)
{
e.Reversed = (reverse > 0);
e.Send();
}
else
{
m.SendMessage(0x55, "Usage: <effect> <range> <speed> <repeat> <reverse>");
}
});
}
public static BaseExplodeEffect CreateInstance(
this ExplodeFX type,
IPoint3D start,
Map map,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
{
switch (type)
{
case ExplodeFX.None:
return null;
case ExplodeFX.Smoke:
return new SmokeExplodeEffect(start, map, range, repeat, interval, effectHandler, callback);
case ExplodeFX.Water:
return new WaterRippleEffect(start, map, range, repeat, interval, effectHandler, callback);
case ExplodeFX.Fire:
return new FireExplodeEffect(start, map, range, repeat, interval, effectHandler, callback);
case ExplodeFX.Earth:
return new EarthExplodeEffect(start, map, range, repeat, interval, effectHandler, callback);
case ExplodeFX.Air:
return new AirExplodeEffect(start, map, range, repeat, interval, effectHandler, callback);
case ExplodeFX.Energy:
return new EnergyExplodeEffect(start, map, range, repeat, interval, effectHandler, callback);
case ExplodeFX.Poison:
return new PoisonExplodeEffect(start, map, range, repeat, interval, effectHandler, callback);
default:
{
var rfx = (ExplodeFX[])Enum.GetValues(typeof(ExplodeFX));
do
{
type = rfx.GetRandom();
}
while (type == ExplodeFX.Random || type == ExplodeFX.None);
return CreateInstance(type, start, map, range, repeat, interval, effectHandler, callback);
}
}
}
}
}
namespace VitaNex.FX
{
public abstract class BaseExplodeEffect : BaseRangedEffect<EffectQueue, EffectInfo>
{
public BaseExplodeEffect(
IPoint3D start,
Map map,
int range = 2,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, range, repeat, interval, effectHandler, callback)
{ }
public override EffectQueue CreateEffectQueue(IEnumerable<EffectInfo> queue)
{
return new EffectQueue(queue, null, EffectHandler, false);
}
public override EffectInfo CloneEffectInfo(EffectInfo src)
{
return new EffectInfo(null, null, src.EffectID, src.Hue, src.Speed, src.Duration, src.Render, src.Delay);
}
}
public class SmokeExplodeEffect : BaseExplodeEffect
{
public static EffectInfo[] Info => new[] { new EffectInfo(null, null, 14120, 0, 10, 10, EffectRender.SemiTransparent) };
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public SmokeExplodeEffect(
IPoint3D start,
Map map,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, range, repeat, interval, effectHandler, callback)
{ }
}
public class WaterRippleEffect : BaseExplodeEffect
{
public static EffectInfo[] Info => new[] { new EffectInfo(null, null, -1, 0, 10, 30) };
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public WaterRippleEffect(
IPoint3D start,
Map map,
int range = 3,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, range, repeat, interval, effectHandler, callback)
{
EnableMutate = true;
}
public override void MutateEffect(EffectInfo e)
{
base.MutateEffect(e);
if (e == null || e.EffectID != -1)
{
return;
}
switch (Utility.GetDirection(Start, e.Source))
{
case Direction.Up:
case Direction.North:
e.EffectID = 8099;
break;
case Direction.Down:
case Direction.South:
e.EffectID = 8114;
break;
case Direction.Right:
case Direction.East:
e.EffectID = 8109;
break;
case Direction.Left:
case Direction.West:
e.EffectID = 8104;
break;
}
}
}
public class FireExplodeEffect : BaseExplodeEffect
{
public static EffectInfo[] Info => new[]
{
new EffectInfo(null, null, 14089, 0, 10, 20, EffectRender.SemiTransparent),
new EffectInfo(null, null, 13401, 0, 10, 20, EffectRender.Normal, TimeSpan.FromMilliseconds(200))
};
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public FireExplodeEffect(
IPoint3D start,
Map map,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, range, repeat, interval, effectHandler, callback)
{ }
}
public class EarthExplodeEffect : BaseExplodeEffect
{
public static EffectInfo[] Info => new[]
{
new EffectInfo(null, null, -1, 0, 10, 20),
new EffectInfo(null, null, 14120, 0, 10, 20, EffectRender.SemiTransparent, TimeSpan.FromMilliseconds(200))
};
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public EarthExplodeEffect(
IPoint3D start,
Map map,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, range, repeat, interval, effectHandler, callback)
{
EnableMutate = true;
}
public override void MutateEffect(EffectInfo e)
{
base.MutateEffect(e);
if (e == null || e.EffectID != -1)
{
return;
}
e.EffectID = Utility.RandomMinMax(4963, 4973);
e.Source = new Entity(Serial.Zero, e.Source.Location.Clone3D(zOffset: 5), e.Map);
}
}
public class AirExplodeEffect : BaseExplodeEffect
{
public static EffectInfo[] Info => new[]
{
new EffectInfo(null, null, 14217, 899, 10, 20, EffectRender.Lighten),
new EffectInfo(null, null, 14284, 899, 10, 30, EffectRender.LightenMore, TimeSpan.FromMilliseconds(200))
};
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public AirExplodeEffect(
IPoint3D start,
Map map,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, range, repeat, interval, effectHandler, callback)
{ }
}
public class EnergyExplodeEffect : BaseExplodeEffect
{
public static EffectInfo[] Info => new[]
{
new EffectInfo(null, null, 14170, 0, 10, 20, EffectRender.LightenMore),
new EffectInfo(null, null, 14201, 0, 10, 30, EffectRender.Normal, TimeSpan.FromMilliseconds(200))
};
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public EnergyExplodeEffect(
IPoint3D start,
Map map,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, range, repeat, interval, effectHandler, callback)
{
EnableMutate = true;
}
public override void MutateEffect(EffectInfo e)
{
base.MutateEffect(e);
if (e != null && e.EffectID == 14201)
{
e.Source = new Entity(Serial.Zero, e.Source.Location.Clone3D(zOffset: -5), e.Map);
}
}
}
public class PoisonExplodeEffect : BaseExplodeEffect
{
public static EffectInfo[] Info => new[]
{
new EffectInfo(null, null, 14217, 65, 10, 30, EffectRender.Darken),
new EffectInfo(null, null, 14120, 65, 10, 30, EffectRender.Normal, TimeSpan.FromMilliseconds(200))
};
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public PoisonExplodeEffect(
IPoint3D start,
Map map,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, range, repeat, interval, effectHandler, callback)
{
EnableMutate = true;
}
public override void MutateEffect(EffectInfo e)
{
base.MutateEffect(e);
if (e != null)
{
e.Hue = Utility.RandomMinMax(550, 580);
}
}
}
}

View File

@@ -0,0 +1,303 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Commands;
using VitaNex.Network;
using Geo = Server.Misc.Geometry;
#endregion
namespace VitaNex.FX
{
public enum SpecialFX
{
None = 0,
Random,
FirePentagram
//-FireSpiral
}
public static class SpecialEffects
{
public static void Initialize()
{
CommandSystem.Register(
"SpecialFXHide",
AccessLevel.GameMaster,
ce =>
{
if (ce == null || ce.Mobile == null)
{
return;
}
var m = ce.Mobile;
if (m.Hidden)
{
m.Hidden = false;
CommandSystem.Entries["SpecialFX"].Handler(ce);
}
else
{
CommandSystem.Entries["SpecialFX"].Handler(ce);
m.Hidden = true;
}
});
CommandSystem.Register(
"SpecialFX",
AccessLevel.GameMaster,
ce =>
{
if (ce == null || ce.Mobile == null)
{
return;
}
var m = ce.Mobile;
if (ce.Arguments.Length < 1 || !Enum.TryParse(ce.Arguments[0], true, out SpecialFX effect))
{
effect = SpecialFX.None;
}
if (ce.Arguments.Length < 2 || !Int32.TryParse(ce.Arguments[1], out var range))
{
range = 5;
}
if (ce.Arguments.Length < 3 || !Int32.TryParse(ce.Arguments[2], out var speed))
{
speed = 10;
}
if (ce.Arguments.Length < 4 || !Int32.TryParse(ce.Arguments[3], out var repeat))
{
repeat = 0;
}
if (ce.Arguments.Length < 5 || !Int32.TryParse(ce.Arguments[4], out var reverse))
{
reverse = 0;
}
range = Math.Max(0, Math.Min(100, range));
speed = Math.Max(1, Math.Min(10, speed));
repeat = Math.Max(0, Math.Min(100, repeat));
reverse = Math.Max(0, Math.Min(1, reverse));
var e = effect.CreateInstance(
m.Location,
m.Map,
range,
repeat,
TimeSpan.FromMilliseconds(1000 - ((speed - 1) * 100)));
if (e != null)
{
e.Reversed = (reverse > 0);
e.Send();
}
else
{
m.SendMessage(0x55, "Usage: <effect> <range> <speed> <repeat> <reverse>");
}
});
}
public static BaseSpecialEffect CreateInstance(
this SpecialFX type,
IPoint3D start,
Map map,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
{
switch (type)
{
case SpecialFX.None:
return null;
case SpecialFX.FirePentagram:
return new FirePentagramEffect(start, map, range, repeat, interval, effectHandler, callback);
/*case SpecialFX.FireSpiral:
return new FireSpiralEffect(start, map, range, repeat, interval, effectHandler, callback);*/
default:
{
var rfx = (SpecialFX[])Enum.GetValues(typeof(SpecialFX));
do
{
type = rfx.GetRandom();
}
while (type == SpecialFX.Random || type == SpecialFX.None);
return CreateInstance(type, start, map, range, repeat, interval, effectHandler, callback);
}
}
}
}
}
namespace VitaNex.FX
{
public abstract class BaseSpecialEffect : BaseRangedEffect<EffectQueue, EffectInfo>
{
public BaseSpecialEffect(
IPoint3D start,
Map map,
int range = 2,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, range, repeat, interval, effectHandler, callback)
{ }
public override EffectQueue CreateEffectQueue(IEnumerable<EffectInfo> queue)
{
return new EffectQueue(queue, null, EffectHandler, false);
}
public override EffectInfo CloneEffectInfo(EffectInfo src)
{
return new EffectInfo(null, null, src.EffectID, src.Hue, src.Speed, src.Duration, src.Render, src.Delay);
}
}
public class FirePentagramEffect : BaseSpecialEffect
{
public static EffectInfo[] Info => new[]
{
new EffectInfo(null, null, 14089, 0, 10, 20, EffectRender.SemiTransparent),
new EffectInfo(null, null, 13401, 0, 10, 20, EffectRender.Normal, TimeSpan.FromMilliseconds(200))
};
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public FirePentagramEffect(
IPoint3D start,
Map map,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, range, repeat, interval, effectHandler, callback)
{ }
private const double Section = 72;
private static readonly double[][] _Lines =
{
new[] {0, Section * 2}, new[] {Section * 2, Section * 4}, new[] {Section * 4, Section}, new[] {Section, Section * 3},
new[] {Section * 3, 0}
};
public override Point3D[][] GetTargetPoints(int count)
{
var points = new List<Point3D>[_Lines.Length];
points.SetAll(i => new List<Point3D>());
_Lines.For(
(i, list) =>
{
var start = Start.Clone3D(
(int)Math.Round(Range * Math.Sin(Geo.DegreesToRadians(list[0]))),
(int)Math.Round(Range * Math.Cos(Geo.DegreesToRadians(list[0]))));
var end = Start.Clone3D(
(int)Math.Round(Range * Math.Sin(Geo.DegreesToRadians(list[1]))),
(int)Math.Round(Range * Math.Cos(Geo.DegreesToRadians(list[1]))));
if (AverageZ)
{
start = start.GetWorldTop(Map);
end = end.GetWorldTop(Map);
}
points[i].AddRange(start.GetLine3D(end, Map));
});
return points.ToMultiArray();
}
}
/*public class FireSpiralEffect : BaseSpecialEffect
{
public static EffectInfo[] Info
{
get
{
return new[]
{
new EffectInfo(null, null, 14089, 0, 10, 20, EffectRender.SemiTransparent),
new EffectInfo(null, null, 13401, 0, 10, 20, EffectRender.Normal, TimeSpan.FromMilliseconds(200))
};
}
}
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects { get { return _Effects; } }
public FireSpiralEffect(
IPoint3D start,
Map map,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, range, repeat, interval, effectHandler, callback)
{ }
public override Point3D[][] GetTargetPoints(int count)
{
List<List<Point3D>> points = new List<List<Point3D>>(Range + 1);
points.SetAll(i => new List<Point3D>());
for (int r = 0; r <= Range; r++)
{
int bound = r * r;
int area = (int)(Math.PI * bound);
int x, y;
for (int t = 0; t <= area; t++)
{
x = (int)(r * Math.Cos(t)) + Start.X;
y = (int)(r * Math.Sin(t)) + Start.Y;
if (x * x + y * y <= bound)
{
points[r].Add(new Point3D(x, y, AverageZ ? Map.GetAverageZ(x, y) : Start.Z));
}
}
}
return points.ToMultiArray();
}
}*/
}

View File

@@ -0,0 +1,668 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Server;
using Server.Commands;
using Server.Movement;
using VitaNex.Network;
#endregion
namespace VitaNex.FX
{
public enum WaveFX
{
None = 0,
Random,
Water,
Fire,
Earth,
Air,
Energy,
Poison,
Tornado
}
public static class WaveEffects
{
public static void Initialize()
{
CommandSystem.Register(
"WaveFX",
AccessLevel.GameMaster,
ce =>
{
var m = ce.Mobile;
if (ce.Arguments.Length < 1 || !Enum.TryParse(ce.Arguments[0], true, out WaveFX effect))
{
effect = WaveFX.None;
}
if (ce.Arguments.Length < 2 || !Int32.TryParse(ce.Arguments[1], out var range))
{
range = 5;
}
if (ce.Arguments.Length < 3 || !Int32.TryParse(ce.Arguments[2], out var speed))
{
speed = 10;
}
if (ce.Arguments.Length < 4 || !Int32.TryParse(ce.Arguments[3], out var repeat))
{
repeat = 0;
}
if (ce.Arguments.Length < 5 || !Int32.TryParse(ce.Arguments[4], out var reverse))
{
reverse = 0;
}
range = Math.Max(0, Math.Min(100, range));
speed = Math.Max(1, Math.Min(10, speed));
repeat = Math.Max(0, Math.Min(100, repeat));
reverse = Math.Max(0, Math.Min(1, reverse));
var e = effect.CreateInstance(
m.Location,
m.Map,
m.Direction,
range,
repeat,
TimeSpan.FromMilliseconds(1000 - ((speed - 1) * 100)));
if (e != null)
{
e.Reversed = (reverse > 0);
e.Send();
}
else
{
m.SendMessage(0x55, "Usage: <effect> <range> <speed> <repeat> <reverse>");
}
});
}
public static BaseWaveEffect CreateInstance(
this WaveFX type,
IPoint3D start,
Map map,
Direction d,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
{
switch (type)
{
case WaveFX.None:
return null;
case WaveFX.Fire:
return new FireWaveEffect(start, map, d, range, repeat, interval, effectHandler, callback);
case WaveFX.Water:
return new WaterWaveEffect(start, map, d, range, repeat, interval, effectHandler, callback);
case WaveFX.Earth:
return new EarthWaveEffect(start, map, d, range, repeat, interval, effectHandler, callback);
case WaveFX.Air:
return new AirWaveEffect(start, map, d, range, repeat, interval, effectHandler, callback);
case WaveFX.Energy:
return new EnergyWaveEffect(start, map, d, range, repeat, interval, effectHandler, callback);
case WaveFX.Poison:
return new PoisonWaveEffect(start, map, d, range, repeat, interval, effectHandler, callback);
case WaveFX.Tornado:
return new TornadoEffect(start, map, d, range, repeat, interval, effectHandler, callback);
default:
{
var rfx = (WaveFX[])Enum.GetValues(typeof(WaveFX));
do
{
type = rfx.GetRandom();
}
while (type == WaveFX.Random || type == WaveFX.None);
return CreateInstance(type, start, map, d, range, repeat, interval, effectHandler, callback);
}
}
}
}
public abstract class BaseWaveEffect : BaseRangedEffect<EffectQueue, EffectInfo>
{
public virtual Direction Direction { get; set; }
public BaseWaveEffect(
IPoint3D start,
Map map,
Direction d,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, range, repeat, interval, effectHandler, callback)
{
Direction = d & Direction.ValueMask;
}
public override EffectQueue CreateEffectQueue(IEnumerable<EffectInfo> queue)
{
return new EffectQueue(queue, null, EffectHandler, false);
}
public override EffectInfo CloneEffectInfo(EffectInfo src)
{
return new EffectInfo(null, null, src.EffectID, src.Hue, src.Speed, src.Duration, src.Render, src.Delay);
}
protected override bool ExcludePoint(Point3D p, int range, Direction fromCenter)
{
switch (Direction & Direction.Mask)
{
case Direction.Up:
return !(fromCenter == Direction.West || fromCenter == Direction.Up || fromCenter == Direction.North);
case Direction.North:
return !(fromCenter == Direction.Up || fromCenter == Direction.North || fromCenter == Direction.Right);
case Direction.Right:
return !(fromCenter == Direction.North || fromCenter == Direction.Right || fromCenter == Direction.East);
case Direction.East:
return !(fromCenter == Direction.Right || fromCenter == Direction.East || fromCenter == Direction.Down);
case Direction.Down:
return !(fromCenter == Direction.East || fromCenter == Direction.Down || fromCenter == Direction.South);
case Direction.South:
return !(fromCenter == Direction.Down || fromCenter == Direction.South || fromCenter == Direction.Left);
case Direction.Left:
return !(fromCenter == Direction.South || fromCenter == Direction.Left || fromCenter == Direction.West);
case Direction.West:
return !(fromCenter == Direction.Left || fromCenter == Direction.West || fromCenter == Direction.Up);
}
return true;
}
}
public class WaterWaveEffect : BaseWaveEffect
{
public static bool DisplayElemental = true;
public static EffectInfo[] Info => new[]
{
new EffectInfo(null, null, 8459, 0, 10, 20),
new EffectInfo(null, null, 14089, 85, 10, 30, EffectRender.SemiTransparent, TimeSpan.FromMilliseconds(200)),
new EffectInfo(null, null, -1, 0, 10, 40, EffectRender.Normal, TimeSpan.FromMilliseconds(400))
};
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public WaterWaveEffect(
IPoint3D start,
Map map,
Direction d,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, d, range, repeat, interval, effectHandler, callback)
{
EnableMutate = true;
}
public override EffectInfo CloneEffectInfo(EffectInfo src)
{
if (src != null && src.EffectID == 8459 && !DisplayElemental)
{
return null;
}
return base.CloneEffectInfo(src);
}
public override void MutateEffect(EffectInfo e)
{
base.MutateEffect(e);
if (e == null || e.EffectID != -1)
{
return;
}
switch (Direction)
{
case Direction.North:
{
switch (Utility.GetDirection(Start, e.Source))
{
case Direction.Up:
case Direction.North:
case Direction.Right:
e.EffectID = 8099;
break;
}
}
break;
case Direction.East:
{
switch (Utility.GetDirection(Start, e.Source))
{
case Direction.Down:
case Direction.East:
case Direction.Right:
e.EffectID = 8109;
break;
}
}
break;
case Direction.South:
{
switch (Utility.GetDirection(Start, e.Source))
{
case Direction.Down:
case Direction.South:
case Direction.Left:
e.EffectID = 8114;
break;
}
}
break;
case Direction.West:
{
switch (Utility.GetDirection(Start, e.Source))
{
case Direction.Up:
case Direction.West:
case Direction.Left:
e.EffectID = 8104;
break;
}
}
break;
default:
{
switch (Utility.GetDirection(Start, e.Source))
{
case Direction.Up:
case Direction.North:
e.EffectID = 8099;
break;
case Direction.Right:
case Direction.East:
e.EffectID = 8109;
break;
case Direction.Down:
case Direction.South:
e.EffectID = 8114;
break;
case Direction.Left:
case Direction.West:
e.EffectID = 8104;
break;
}
}
break;
}
}
}
public class FireWaveEffect : BaseWaveEffect
{
public static bool DisplayElemental = true;
public static EffectInfo[] Info => new[]
{
new EffectInfo(null, null, 8435, 0, 10, 20),
new EffectInfo(null, null, 14089, 0, 10, 20, EffectRender.SemiTransparent, TimeSpan.FromMilliseconds(200)),
new EffectInfo(null, null, 13401, 0, 10, 20, EffectRender.Normal, TimeSpan.FromMilliseconds(200))
};
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public FireWaveEffect(
IPoint3D start,
Map map,
Direction d,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, d, range, repeat, interval, effectHandler, callback)
{
EnableMutate = true;
}
public override EffectInfo CloneEffectInfo(EffectInfo src)
{
if (src != null && src.EffectID == 8435 && !DisplayElemental)
{
return null;
}
return base.CloneEffectInfo(src);
}
}
public class EarthWaveEffect : BaseWaveEffect
{
public static bool DisplayElemental = true;
public static EffectInfo[] Info => new[]
{
new EffectInfo(null, null, 8407, 0, 10, 20),
new EffectInfo(null, null, -1, 0, 10, 20, EffectRender.Normal, TimeSpan.FromMilliseconds(200)),
new EffectInfo(null, null, 14120, 0, 10, 20, EffectRender.SemiTransparent, TimeSpan.FromMilliseconds(400))
};
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public EarthWaveEffect(
IPoint3D start,
Map map,
Direction d,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, d, range, repeat, interval, effectHandler, callback)
{
EnableMutate = true;
}
public override EffectInfo CloneEffectInfo(EffectInfo src)
{
if (src != null && src.EffectID == 8407 && !DisplayElemental)
{
return null;
}
return base.CloneEffectInfo(src);
}
public override void MutateEffect(EffectInfo e)
{
base.MutateEffect(e);
if (e == null || e.EffectID != -1)
{
return;
}
e.EffectID = Utility.RandomMinMax(4963, 4973);
e.Source = new Entity(Serial.Zero, e.Source.Location.Clone3D(zOffset: 5), e.Map);
}
}
public class AirWaveEffect : BaseWaveEffect
{
public static bool DisplayElemental = true;
public static EffectInfo[] Info => new[]
{
new EffectInfo(null, null, 8429, 0, 10, 20),
new EffectInfo(null, null, 14217, 899, 10, 30, EffectRender.Lighten, TimeSpan.FromMilliseconds(200)),
new EffectInfo(null, null, 14284, 899, 10, 40, EffectRender.LightenMore, TimeSpan.FromMilliseconds(400))
};
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public AirWaveEffect(
IPoint3D start,
Map map,
Direction d,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, d, range, repeat, interval, effectHandler, callback)
{
EnableMutate = true;
}
public override EffectInfo CloneEffectInfo(EffectInfo src)
{
if (src != null && src.EffectID == 8429 && !DisplayElemental)
{
return null;
}
return base.CloneEffectInfo(src);
}
}
public class EnergyWaveEffect : BaseWaveEffect
{
public static EffectInfo[] Info => new[]
{
new EffectInfo(null, null, 8448, 0, 10, 20),
new EffectInfo(null, null, 14170, 0, 10, 30, EffectRender.LightenMore, TimeSpan.FromMilliseconds(200)),
new EffectInfo(null, null, 14201, 0, 10, 40, EffectRender.Normal, TimeSpan.FromMilliseconds(400))
};
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public EnergyWaveEffect(
IPoint3D start,
Map map,
Direction d,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, d, range, repeat, interval, effectHandler, callback)
{
EnableMutate = true;
}
public override void MutateEffect(EffectInfo e)
{
base.MutateEffect(e);
if (e == null)
{
return;
}
switch (e.EffectID)
{
case 8448:
e.Source = new Entity(Serial.Zero, e.Source.Location.Clone3D(zOffset: -10), e.Map);
break;
case 14201:
e.Source = new Entity(Serial.Zero, e.Source.Location.Clone3D(zOffset: -5), e.Map);
break;
}
}
}
public class PoisonWaveEffect : BaseWaveEffect
{
public static EffectInfo[] Info => new[]
{
new EffectInfo(null, null, -1, 0, 10, 20),
new EffectInfo(null, null, 14217, 65, 10, 30, EffectRender.Darken, TimeSpan.FromMilliseconds(200)),
new EffectInfo(null, null, 14120, 65, 10, 40, EffectRender.Normal, TimeSpan.FromMilliseconds(400))
};
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public PoisonWaveEffect(
IPoint3D start,
Map map,
Direction d,
int range = 5,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, d, range, repeat, interval, effectHandler, callback)
{
EnableMutate = true;
}
public override void MutateEffect(EffectInfo e)
{
base.MutateEffect(e);
if (e == null)
{
return;
}
switch (e.EffectID)
{
case -1:
e.EffectID = Utility.RandomMinMax(11666, 11668);
break;
default:
e.Hue = Utility.RandomMinMax(550, 580);
break;
}
}
}
public class TornadoEffect : BaseWaveEffect
{
public static EffectInfo[] Info => new[] { new EffectInfo(null, null, 14284, 899, 10, 10, EffectRender.ShadowOutline) };
private readonly EffectInfo[] _Effects = Info;
public override EffectInfo[] Effects => _Effects;
public int Size { get; set; }
public int Climb { get; set; }
public int Height { get; set; }
public bool CanMove { get; set; }
public TornadoEffect(
IPoint3D start,
Map map,
Direction d,
int range = 10,
int repeat = 0,
TimeSpan? interval = null,
Action<EffectInfo> effectHandler = null,
Action callback = null)
: base(start, map, d, range, repeat, interval, effectHandler, callback)
{
EnableMutate = true;
Size = 5;
Climb = 5;
Height = 80;
CanMove = true;
}
protected override bool ExcludePoint(Point3D p, int range, Direction fromCenter)
{
return false;
}
public override void MutateEffect(EffectInfo e)
{
base.MutateEffect(e);
e.Duration = 7 + (int)(Interval.TotalMilliseconds / 100.0);
switch (Utility.Random(3))
{
case 0:
e.Render = EffectRender.Darken;
break;
case 1:
e.Render = EffectRender.SemiTransparent;
break;
case 2:
e.Render = EffectRender.ShadowOutline;
break;
}
}
public override Point3D[][] GetTargetPoints(int count)
{
var start = Start.Clone3D();
int x = 0, y = 0;
if (CanMove)
{
Movement.Offset(Direction, ref x, ref y);
}
var end = start.Clone3D(Range * x, Range * y);
if (AverageZ)
{
start = start.GetWorldTop(Map);
end = end.GetWorldTop(Map);
}
var path = CanMove ? start.GetLine3D(end, Map, AverageZ) : new[] { start };
var points = new List<Point3D>[path.Length];
points.SetAll(i => new List<Point3D>());
var climb = Climb;
var size = Size;
double height = Height;
Action<int> a = i =>
{
var step = path[i];
for (var z = 0; z < height; z += climb)
{
var mm = (int)Math.Max(0, size * (z / height));
points[i].AddRange(step.ScanRangeGet(Map, mm, mm, ComputePoint, false).Combine().Select(p => p.Clone3D(0, 0, z)));
}
};
if (path.Length < 10)
{
for (var i = 0; i < path.Length; i++)
{
a(i);
}
}
else
{
Parallel.For(0, path.Length, a);
}
return points.FreeToMultiArray(true);
}
}
}