Effects packets (#308)

- [X] Changes effect packets
- [X] Updates playing sounds
- [X] Updates Effects class to have more options so there are less direct calls to building the packets
- [X] Changes bonding status packet
This commit is contained in:
Kamron Batman 2020-11-12 00:52:38 -08:00 committed by GitHub
parent 1c9439e4fd
commit 361ec4dba4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 958 additions and 833 deletions

View file

@ -1,5 +1,4 @@
using System;
using System.Buffers;
using Server.Network;
using Xunit;
@ -7,6 +6,21 @@ namespace Server.Tests.Network
{
public class EffectPackets
{
[Theory]
[InlineData(10, 1000, 10, 5)]
public void TestSoundEffect(ushort soundID, int x, int y, int z)
{
var p = new Point3D(x, y, z);
var expected = new PlaySound(soundID, p).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSoundEffect(soundID, p);
var result = ns.SendPipe.Reader.TryRead();
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
}
[Fact]
public void TestParticleEffect()
{
@ -29,56 +43,21 @@ namespace Server.Tests.Network
byte layer = 9;
ushort unknown = 0;
var data = new ParticleEffect(
effectType,
from,
to,
itemId,
fromPoint,
toPoint,
speed,
duration,
direction,
explode,
hue,
renderMode,
effect,
explodeEffect,
explodeSound,
serial,
layer,
var expected = new ParticleEffect(
effectType, from, to, itemId, fromPoint, toPoint, speed, duration, direction,
explode, hue, renderMode, effect, explodeEffect, explodeSound, serial, layer,
unknown
).Compile();
Span<byte> expectedData = stackalloc byte[49];
Span<byte> actual = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength];
OutgoingEffectPackets.CreateParticleEffect(
ref actual,
effectType, from, to, itemId, fromPoint, toPoint, speed, duration, direction,
explode, hue, renderMode, effect, explodeEffect, explodeSound, serial, layer,
unknown
);
var pos = 0;
expectedData.Write(ref pos, (byte)0xC7); // Packet ID
expectedData.Write(ref pos, (byte)effectType);
expectedData.Write(ref pos, from);
expectedData.Write(ref pos, to);
expectedData.Write(ref pos, (ushort)itemId);
expectedData.Write(ref pos, fromPoint);
expectedData.Write(ref pos, toPoint);
expectedData.Write(ref pos, speed);
expectedData.Write(ref pos, duration);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)0);
#else
pos += 2;
#endif
expectedData.Write(ref pos, direction);
expectedData.Write(ref pos, explode);
expectedData.Write(ref pos, hue);
expectedData.Write(ref pos, renderMode);
expectedData.Write(ref pos, effect);
expectedData.Write(ref pos, explodeEffect);
expectedData.Write(ref pos, explodeSound);
expectedData.Write(ref pos, serial);
expectedData.Write(ref pos, layer);
expectedData.Write(ref pos, unknown);
AssertThat.Equal(data, expectedData);
AssertThat.Equal(actual, expected);
}
[Fact]
@ -97,74 +76,33 @@ namespace Server.Tests.Network
var hue = 0x1024;
var renderMode = 1;
var data = new HuedEffect(
effectType,
from,
to,
itemId,
fromPoint,
toPoint,
speed,
duration,
direction,
explode,
hue,
renderMode
var expected = new HuedEffect(
effectType, from, to, itemId, fromPoint, toPoint, speed,
duration, direction, explode, hue, renderMode
).Compile();
Span<byte> expectedData = stackalloc byte[36];
Span<byte> actual = stackalloc byte[OutgoingEffectPackets.HuedEffectLength];
OutgoingEffectPackets.CreateHuedEffect(
ref actual,
effectType, from, to, itemId, fromPoint, toPoint, speed,
duration, direction, explode, hue, renderMode
);
var pos = 0;
expectedData.Write(ref pos, (byte)0xC0); // Packet ID
expectedData.Write(ref pos, (byte)effectType);
expectedData.Write(ref pos, from);
expectedData.Write(ref pos, to);
expectedData.Write(ref pos, (ushort)itemId);
expectedData.Write(ref pos, fromPoint);
expectedData.Write(ref pos, toPoint);
expectedData.Write(ref pos, speed);
expectedData.Write(ref pos, duration);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)0);
#else
pos += 2;
#endif
expectedData.Write(ref pos, direction);
expectedData.Write(ref pos, explode);
expectedData.Write(ref pos, hue);
expectedData.Write(ref pos, renderMode);
AssertThat.Equal(data, expectedData);
AssertThat.Equal(actual, expected);
}
[Fact]
public void TestScreenEffect()
[Theory]
[InlineData(ScreenEffectType.DarkFlash)]
[InlineData(ScreenEffectType.FadeInOut)]
public void TestScreenEffect(ScreenEffectType screenType)
{
var type = ScreenEffectType.FadeOut;
var data = new ScreenEffect(type).Compile();
var expected = new ScreenEffect(screenType).Compile();
Span<byte> expectedData = stackalloc byte[28];
var pos = 0;
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendScreenEffect(screenType);
expectedData.Write(ref pos, (byte)0x70); // Packet ID
expectedData.Write(ref pos, (byte)0x04); // Effect
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, 0);
#else
pos += 8;
#endif
expectedData.Write(ref pos, (ushort)type); // Screen Effect Type
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, 0);
#endif
AssertThat.Equal(data, expectedData);
var result = ns.SendPipe.Reader.TryRead();
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
}
[Fact]
@ -172,32 +110,15 @@ namespace Server.Tests.Network
{
IEntity entity = new Entity(0x1000, new Point3D(1000, 100, -10), Map.Felucca);
var hue = 0x1024;
var data = new BoltEffect(entity, hue).Compile();
var expected = new BoltEffect(entity, hue).Compile();
Span<byte> expectedData = stackalloc byte[36];
var pos = 0;
expectedData.Write(ref pos, (byte)0xC0); // Packet ID
expectedData.Write(ref pos, (byte)0x01); // Effect
Span<byte> actual = stackalloc byte[OutgoingEffectPackets.BoltEffectLength];
OutgoingEffectPackets.CreateBoltEffect(
ref actual,
entity, hue
);
expectedData.Write(ref pos, entity.Serial);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, (ushort)0);
#else
pos += 6;
#endif
expectedData.Write(ref pos, entity.Location);
expectedData.Write(ref pos, entity.Location);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, (ushort)0);
#else
pos += 6;
#endif
expectedData.Write(ref pos, hue);
AssertThat.Equal(data, expectedData);
AssertThat.Equal(actual, expected);
}
}
}

View file

@ -15,48 +15,21 @@
namespace Server.Network
{
public enum EffectType
public sealed class PlaySound : Packet
{
Moving,
Lightning,
FixedXYZ,
FixedFrom
public PlaySound(int soundID, IPoint3D target) : base(0x54, 12)
{
Stream.Write((byte)1); // flags
Stream.Write((short)soundID);
Stream.Write((short)0); // volume
Stream.Write((short)target.X);
Stream.Write((short)target.Y);
Stream.Write((short)target.Z);
}
}
public class ParticleEffect : Packet
{
public ParticleEffect(
EffectType type, Serial from, Serial to, int itemID, Point3D fromPoint, Point3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode, int effect,
int explodeEffect, int explodeSound, Serial serial, int layer, int unknown
) : base(0xC7, 49)
{
Stream.Write((byte)type);
Stream.Write(from);
Stream.Write(to);
Stream.Write((short)itemID);
Stream.Write((short)fromPoint.m_X);
Stream.Write((short)fromPoint.m_Y);
Stream.Write((sbyte)fromPoint.m_Z);
Stream.Write((short)toPoint.m_X);
Stream.Write((short)toPoint.m_Y);
Stream.Write((sbyte)toPoint.m_Z);
Stream.Write((byte)speed);
Stream.Write((byte)duration);
Stream.Write((byte)0);
Stream.Write((byte)0);
Stream.Write(fixedDirection);
Stream.Write(explode);
Stream.Write(hue);
Stream.Write(renderMode);
Stream.Write((short)effect);
Stream.Write((short)explodeEffect);
Stream.Write((short)explodeSound);
Stream.Write(serial);
Stream.Write((byte)layer);
Stream.Write((short)unknown);
}
public ParticleEffect(
EffectType type, Serial from, Serial to, int itemID, IPoint3D fromPoint, IPoint3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode, int effect,
@ -92,31 +65,6 @@ namespace Server.Network
public class HuedEffect : Packet
{
public HuedEffect(
EffectType type, Serial from, Serial to, int itemID, Point3D fromPoint, Point3D toPoint, int speed,
int duration, bool fixedDirection, bool explode, int hue, int renderMode
) : base(0xC0, 36)
{
Stream.Write((byte)type);
Stream.Write(from);
Stream.Write(to);
Stream.Write((short)itemID);
Stream.Write((short)fromPoint.m_X);
Stream.Write((short)fromPoint.m_Y);
Stream.Write((sbyte)fromPoint.m_Z);
Stream.Write((short)toPoint.m_X);
Stream.Write((short)toPoint.m_Y);
Stream.Write((sbyte)toPoint.m_Z);
Stream.Write((byte)speed);
Stream.Write((byte)duration);
Stream.Write((byte)0);
Stream.Write((byte)0);
Stream.Write(fixedDirection);
Stream.Write(explode);
Stream.Write(hue);
Stream.Write(renderMode);
}
public HuedEffect(
EffectType type, Serial from, Serial to, int itemID, IPoint3D fromPoint, IPoint3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode
@ -294,15 +242,6 @@ namespace Server.Network
}
}
public enum ScreenEffectType
{
FadeOut = 0x00,
FadeIn = 0x01,
LightFlash = 0x02,
FadeInOut = 0x03,
DarkFlash = 0x04
}
public class ScreenEffect : Packet
{
public ScreenEffect(ScreenEffectType type)
@ -315,56 +254,6 @@ namespace Server.Network
}
}
public sealed class ScreenFadeOut : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenFadeOut());
public ScreenFadeOut()
: base(ScreenEffectType.FadeOut)
{
}
}
public sealed class ScreenFadeIn : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenFadeIn());
public ScreenFadeIn()
: base(ScreenEffectType.FadeIn)
{
}
}
public sealed class ScreenFadeInOut : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenFadeInOut());
public ScreenFadeInOut()
: base(ScreenEffectType.FadeInOut)
{
}
}
public sealed class ScreenLightFlash : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenLightFlash());
public ScreenLightFlash()
: base(ScreenEffectType.LightFlash)
{
}
}
public sealed class ScreenDarkFlash : ScreenEffect
{
public static readonly Packet Instance = SetStatic(new ScreenDarkFlash());
public ScreenDarkFlash()
: base(ScreenEffectType.DarkFlash)
{
}
}
public sealed class BoltEffect : Packet
{
public BoltEffect(IEntity target, int hue) : base(0xC0, 36)

View file

@ -2,7 +2,7 @@
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: DisplayHuePicker.cs *
* File: MobilePackets.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@ -13,17 +13,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using Server.HuePickers;
using Server.Network;
namespace Server.Network
namespace Server.Tests.Network
{
public sealed class DisplayHuePicker : Packet
public sealed class BondedStatus : Packet
{
public DisplayHuePicker(HuePicker huePicker) : base(0x95, 9)
public BondedStatus(Serial serial, bool bonded) : base(0xBF)
{
Stream.Write(huePicker.Serial);
Stream.Write((short)0);
Stream.Write((short)huePicker.ItemID);
EnsureCapacity(11);
Stream.Write((short)0x19);
Stream.Write((byte)0);
Stream.Write(serial);
Stream.Write((byte)(bonded ? 1 : 0));
}
}
}

View file

@ -388,35 +388,6 @@ namespace Server.Tests.Network
AssertThat.Equal(data, expectedData);
}
[Theory]
[InlineData(10, 1000, 10, 5)]
public void TestPlaySound(ushort soundID, int x, int y, int z)
{
var p = new Point3D(x, y, z);
var data = new PlaySound(soundID, p).Compile();
Span<byte> expectedData = stackalloc byte[12];
var pos = 0;
expectedData.Write(ref pos, (byte)0x54); // Packet ID
expectedData.Write(ref pos, (byte)1); // Flags
expectedData.Write(ref pos, soundID);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)0); // Volume
#else
pos += 2;
#endif
expectedData.Write(ref pos, (ushort)p.X);
expectedData.Write(ref pos, (ushort)p.Y);
expectedData.Write(ref pos, (short)p.Z);
AssertThat.Equal(data, expectedData);
}
[Theory]
[InlineData(MusicName.Approach)]
[InlineData(MusicName.Combat1)]

View file

@ -1,7 +1,40 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Effects.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using Server.Network;
namespace Server
{
public enum EffectType
{
Moving,
Lightning,
FixedXYZ,
FixedFrom
}
public enum ScreenEffectType
{
FadeOut = 0x00,
FadeIn = 0x01,
LightFlash = 0x02,
FadeInOut = 0x03,
DarkFlash = 0x04
}
public enum EffectLayer
{
Head = 0,
@ -28,7 +61,9 @@ namespace Server
ParticleSupportType == ParticleSupportType.Full ||
ParticleSupportType == ParticleSupportType.Detect && state.IsUOTDClient;
public static void PlaySound(IPoint3D p, Map map, int soundID)
public static void PlaySound(IEntity e, int soundID) => PlaySound(e.Location, e.Map, soundID);
public static void PlaySound(Point3D p, Map map, int soundID)
{
if (soundID <= -1)
{
@ -37,36 +72,22 @@ namespace Server
if (map != null)
{
Packet playSound = null;
Span<byte> buffer = stackalloc byte[OutgoingEffectPackets.SoundPacketLength];
OutgoingEffectPackets.CreateSoundEffect(ref buffer, soundID, p);
var eable = map.GetClientsInRange(new Point3D(p));
foreach (var state in eable)
{
state.Mobile.ProcessDelta();
playSound ??= Packet.Acquire(new PlaySound(soundID, p));
state.Send(playSound);
state.Send(buffer);
}
Packet.Release(playSound);
eable.Free();
}
}
public static void SendBoltEffect(IEntity e)
{
SendBoltEffect(e, true, 0);
}
public static void SendBoltEffect(IEntity e, bool sound)
{
SendBoltEffect(e, sound, 0);
}
public static void SendBoltEffect(IEntity e, bool sound, int hue)
public static void SendBoltEffect(IEntity e, bool sound = true, int hue = 0)
{
var map = e.Map;
@ -77,7 +98,20 @@ namespace Server
e.ProcessDelta();
Packet preEffect = null, boltEffect = null, playSound = null;
Span<byte> preEffect = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength];
OutgoingEffectPackets.CreateTargetParticleEffect(
ref preEffect,
e, 0, 10, 5, 0, 0, 5031, 3, 0
);
Span<byte> boltEffect = stackalloc byte[OutgoingEffectPackets.BoltEffectLength];
OutgoingEffectPackets.CreateBoltEffect(ref boltEffect, e, hue);
Span<byte> soundEffect = sound ? stackalloc byte[OutgoingEffectPackets.SoundPacketLength] : null;
if (sound)
{
OutgoingEffectPackets.CreateSoundEffect(ref soundEffect, 0x29, e);
}
var eable = map.GetClientsInRange(e.Location);
@ -87,52 +121,36 @@ namespace Server
{
if (SendParticlesTo(state))
{
preEffect ??= Packet.Acquire(new TargetParticleEffect(e, 0, 10, 5, 0, 0, 5031, 3, 0));
state.Send(preEffect);
}
boltEffect ??= Packet.Acquire(new BoltEffect(e, hue));
state.Send(boltEffect);
if (sound)
{
playSound ??= Packet.Acquire(new PlaySound(0x29, e));
state.Send(playSound);
state.Send(soundEffect);
}
}
}
Packet.Release(preEffect);
Packet.Release(boltEffect);
Packet.Release(playSound);
eable.Free();
}
public static void SendLocationEffect(IPoint3D p, Map map, int itemID, int duration)
{
SendLocationEffect(p, map, itemID, duration, 10, 0, 0);
}
public static void SendLocationEffect(IPoint3D p, Map map, int itemID, int duration, int speed)
{
SendLocationEffect(p, map, itemID, duration, speed, 0, 0);
}
public static void SendLocationEffect(IPoint3D p, Map map, int itemID, int duration, int hue, int renderMode)
{
SendLocationEffect(p, map, itemID, duration, 10, hue, renderMode);
}
public static void SendLocationEffect(
IEntity e, int itemID, int duration, int speed = 10, int hue = 0, int renderMode = 0
) => SendLocationEffect(e.Location, e.Map, itemID, duration, speed, hue, renderMode);
public static void SendLocationEffect(
IPoint3D p, Map map, int itemID, int duration, int speed, int hue,
int renderMode
Point3D p, Map map, int itemID, int duration, int speed = 10, int hue = 0, int renderMode = 0
)
{
SendPacket(p, map, new LocationEffect(p, itemID, speed, duration, hue, renderMode));
Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength];
OutgoingEffectPackets.CreateLocationHuedEffect(
ref effect,
p, itemID, speed, duration, hue, renderMode
);
SendPacket(p, map, ref effect);
}
public static void SendLocationParticles(IEntity e, int itemID, int speed, int duration, int effect)
@ -146,71 +164,61 @@ namespace Server
}
public static void SendLocationParticles(
IEntity e, int itemID, int speed, int duration, int hue, int renderMode,
int effect, int unknown
IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect, int unknown
)
{
var map = e.Map;
if (map != null)
if (map == null)
{
Packet particles = null, regular = null;
return;
}
var eable = map.GetClientsInRange(e.Location);
Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength];
OutgoingEffectPackets.CreateLocationParticleEffect(
ref particles,
e, itemID, speed, duration, hue, renderMode, effect, unknown
);
foreach (var state in eable)
Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength] : null;
if (itemID != 0)
{
OutgoingEffectPackets.CreateLocationHuedEffect(
ref regular,
e.Location, itemID, speed, duration, hue, renderMode
);
}
var eable = map.GetClientsInRange(e.Location);
foreach (var state in eable)
{
state.Mobile.ProcessDelta();
if (SendParticlesTo(state))
{
state.Mobile.ProcessDelta();
if (SendParticlesTo(state))
{
particles ??=
Packet.Acquire(
new LocationParticleEffect(e, itemID, speed, duration, hue, renderMode, effect, unknown)
);
state.Send(particles);
}
else if (itemID != 0)
{
regular ??= Packet.Acquire(new LocationEffect(e, itemID, speed, duration, hue, renderMode));
state.Send(regular);
}
state.Send(particles);
}
else if (itemID != 0)
{
state.Send(regular);
}
Packet.Release(particles);
Packet.Release(regular);
eable.Free();
}
// SendPacket( e.Location, e.Map, new LocationParticleEffect( e, itemID, speed, duration, hue, renderMode, effect, unknown ) );
eable.Free();
}
public static void SendTargetEffect(IEntity target, int itemID, int duration)
public static void SendTargetEffect(IEntity target, int itemID, int speed, int duration, int hue = 0, int renderMode = 0)
{
SendTargetEffect(target, itemID, duration, 0, 0);
}
(target as Mobile)?.ProcessDelta();
public static void SendTargetEffect(IEntity target, int itemID, int speed, int duration)
{
SendTargetEffect(target, itemID, speed, duration, 0, 0);
}
Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength];
OutgoingEffectPackets.CreateTargetHuedEffect(
ref effect,
target, itemID, speed, duration, hue, renderMode
);
public static void SendTargetEffect(IEntity target, int itemID, int duration, int hue, int renderMode)
{
SendTargetEffect(target, itemID, 10, duration, hue, renderMode);
}
public static void SendTargetEffect(IEntity target, int itemID, int speed, int duration, int hue, int renderMode)
{
if (target is Mobile mobile)
{
mobile.ProcessDelta();
}
SendPacket(target.Location, target.Map, new TargetEffect(target, itemID, speed, duration, hue, renderMode));
SendPacket(target.Location, target.Map, ref effect);
}
public static void SendTargetParticles(
@ -218,121 +226,184 @@ namespace Server
EffectLayer layer
)
{
SendTargetParticles(target, itemID, speed, duration, 0, 0, effect, layer, 0);
}
public static void SendTargetParticles(
IEntity target, int itemID, int speed, int duration, int effect,
EffectLayer layer, int unknown
)
{
SendTargetParticles(target, itemID, speed, duration, 0, 0, effect, layer, unknown);
SendTargetParticles(target, itemID, speed, duration, 0, 0, effect, layer);
}
public static void SendTargetParticles(
IEntity target, int itemID, int speed, int duration, int hue, int renderMode,
int effect, EffectLayer layer, int unknown
int effect, EffectLayer layer, int unknown = 0
)
{
if (target is Mobile mobile)
{
mobile.ProcessDelta();
}
(target as Mobile)?.ProcessDelta();
var map = target.Map;
if (map != null)
if (map == null)
{
Packet particles = null, regular = null;
var eable = map.GetClientsInRange(target.Location);
foreach (var state in eable)
{
state.Mobile.ProcessDelta();
if (SendParticlesTo(state))
{
particles ??= Packet.Acquire(
new TargetParticleEffect(
target,
itemID,
speed,
duration,
hue,
renderMode,
effect,
(int)layer,
unknown
)
);
state.Send(particles);
}
else if (itemID != 0)
{
regular ??= Packet.Acquire(new TargetEffect(target, itemID, speed, duration, hue, renderMode));
state.Send(regular);
}
}
Packet.Release(particles);
Packet.Release(regular);
eable.Free();
return;
}
// SendPacket( target.Location, target.Map, new TargetParticleEffect( target, itemID, speed, duration, hue, renderMode, effect, (int)layer, unknown ) );
Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength];
OutgoingEffectPackets.CreateTargetParticleEffect(
ref particles,
target, itemID, speed, duration, hue, renderMode, effect, (int)layer, unknown
);
Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength] : null;
if (itemID != 0)
{
OutgoingEffectPackets.CreateTargetHuedEffect(ref regular, target, itemID, speed, duration, hue, renderMode);
}
var eable = map.GetClientsInRange(target.Location);
foreach (var state in eable)
{
state.Mobile.ProcessDelta();
if (SendParticlesTo(state))
{
state.Send(particles);
}
else if (itemID != 0)
{
state.Send(regular);
}
}
eable.Free();
}
public static void SendMovingEffect(
IEntity from, IEntity to, int itemID, int speed, int duration,
bool fixedDirection, bool explodes, int hue = 0, int renderMode = 0
Map map, int itemID, Point3D from, Point3D to, int speed, int duration,
bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
) => SendMovingEffect(
Serial.Zero,
Serial.Zero,
from,
map,
itemID,
from,
to,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
);
public static void SendMovingEffect(
Point3D origin, Map map, int itemID, Point3D from, Point3D to, int speed, int duration,
bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
) => SendMovingEffect(
Serial.Zero,
Serial.Zero,
origin,
map,
itemID,
from,
to,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
);
public static void SendMovingEffect(
IEntity from, Point3D to, int itemID,
int speed, int duration, bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
)
{
if (from is Mobile mobile)
{
mobile.ProcessDelta();
}
(from as Mobile)?.ProcessDelta();
if (to is Mobile mobile1)
{
mobile1.ProcessDelta();
}
SendPacket(
SendMovingEffect(
from.Serial,
Serial.Zero,
from.Location,
from.Map,
new MovingEffect(from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode)
);
}
public static void SendMovingParticles(
IEntity from, IEntity to, int itemID, int speed, int duration,
bool fixedDirection, bool explodes, int effect, int explodeEffect, int explodeSound
)
{
SendMovingParticles(
from,
to,
itemID,
from.Location,
to,
speed,
duration,
fixedDirection,
explodes,
0,
0,
effect,
explodeEffect,
explodeSound,
0
hue,
renderMode
);
}
public static void SendMovingEffect(
IEntity from, IEntity to, int itemID,
int speed, int duration, bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
)
{
(from as Mobile)?.ProcessDelta();
(to as Mobile)?.ProcessDelta();
SendMovingEffect(
from,
to,
from.Location,
from.Map,
itemID,
from.Location,
to.Location,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
);
}
public static void SendMovingEffect(
IEntity from, IEntity to, Point3D origin, Map map, int itemID, Point3D fromLocation, Point3D toLocation,
int speed, int duration, bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
)
{
(from as Mobile)?.ProcessDelta();
(to as Mobile)?.ProcessDelta();
SendMovingEffect(
from.Serial,
to.Serial,
origin,
map,
itemID,
fromLocation,
toLocation,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
);
}
public static void SendMovingEffect(
Serial from, Serial to, Point3D origin, Map map, int itemID, Point3D fromLocation, Point3D toLocation,
int speed, int duration, bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
)
{
Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength];
OutgoingEffectPackets.CreateMovingHuedEffect(
ref effect,
from, to, itemID, fromLocation, toLocation, speed, duration, fixedDirection,
explodes, hue, renderMode
);
SendPacket(origin, map, ref effect);
}
public static void SendMovingParticles(
IEntity from, IEntity to, int itemID, int speed, int duration,
bool fixedDirection, bool explodes, int effect, int explodeEffect, int explodeSound, int unknown
bool fixedDirection, bool explodes, int effect, int explodeEffect, int explodeSound, int unknown = 0
)
{
SendMovingParticles(
@ -382,103 +453,52 @@ namespace Server
EffectLayer layer, int unknown
)
{
if (from is Mobile fromMob)
{
fromMob.ProcessDelta();
}
if (to is Mobile toMob)
{
toMob.ProcessDelta();
}
(from as Mobile)?.ProcessDelta();
(to as Mobile)?.ProcessDelta();
var map = from.Map;
if (map != null)
{
Packet particles = null, regular = null;
var eable = map.GetClientsInRange(from.Location);
foreach (var state in eable)
{
state.Mobile.ProcessDelta();
if (SendParticlesTo(state))
{
particles ??= Packet.Acquire(
new MovingParticleEffect(
from,
to,
itemID,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode,
effect,
explodeEffect,
explodeSound,
layer,
unknown
)
);
state.Send(particles);
}
else if (itemID > 1)
{
regular ??= Packet.Acquire(
new MovingEffect(
from,
to,
itemID,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
)
);
state.Send(regular);
}
}
Packet.Release(particles);
Packet.Release(regular);
eable.Free();
}
// SendPacket( from.Location, from.Map, new MovingParticleEffect( from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode, effect, explodeEffect, explodeSound, unknown ) );
}
public static void SendPacket(Point3D origin, Map map, Packet p)
{
if (map == null)
{
return;
}
var eable = map.GetClientsInRange(origin);
Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength];
OutgoingEffectPackets.CreateMovingParticleEffect(
ref particles,
from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode, effect,
explodeEffect, explodeSound, layer, unknown
);
p.Acquire();
Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength] : null;
if (itemID != 0)
{
OutgoingEffectPackets.CreateMovingHuedEffect(
ref regular,
from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode
);
}
var eable = map.GetClientsInRange(from.Location);
foreach (var state in eable)
{
state.Mobile.ProcessDelta();
state.Send(p);
}
p.Release();
if (SendParticlesTo(state))
{
state.Send(particles);
}
else if (itemID > 1)
{
state.Send(regular);
}
}
eable.Free();
}
public static void SendPacket(IPoint3D origin, Map map, Packet p)
public static void SendPacket(Point3D origin, Map map, ref Span<byte> effectBuffer)
{
if (map == null)
{
@ -487,16 +507,12 @@ namespace Server
var eable = map.GetClientsInRange(new Point3D(origin));
p.Acquire();
foreach (var state in eable)
{
state.Mobile.ProcessDelta();
state.Send(p);
state.Send(effectBuffer);
}
p.Release();
eable.Free();
}
}

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Text;
using Server.Accounting;
@ -3374,12 +3375,14 @@ namespace Server
Packet hitsPacket = null;
Packet statPacketTrue = null;
Packet statPacketFalse = null;
Packet deadPacket = null;
Packet hairPacket = null;
Packet facialhairPacket = null;
Packet hbpPacket = null;
Packet hbyPacket = null;
Span<byte> deadBuffer = stackalloc byte[OutgoingMobilePackets.BondedStatusPacketLength];
OutgoingMobilePackets.CreateBondedStatus(ref deadBuffer, m.Serial, true);
var eable = m.Map.GetClientsInRange(m.m_Location);
foreach (var state in eable)
@ -3399,9 +3402,7 @@ namespace Server
if (m.IsDeadBondedPet)
{
deadPacket ??= Packet.Acquire(new BondedStatus(m.Serial, true));
state.Send(deadPacket);
state.Send(deadBuffer);
}
}
@ -3502,7 +3503,6 @@ namespace Server
Packet.Release(hitsPacket);
Packet.Release(statPacketTrue);
Packet.Release(statPacketFalse);
Packet.Release(deadPacket);
Packet.Release(hairPacket);
Packet.Release(facialhairPacket);
Packet.Release(hbpPacket);
@ -5383,7 +5383,7 @@ namespace Server
if (sound >= 0)
{
Effects.PlaySound(this, Map, sound);
Effects.PlaySound(this, sound);
}
if (!m_Player)
@ -5660,12 +5660,7 @@ namespace Server
from.Holding = item;
var liftSound = item.GetLiftSound(from);
if (liftSound != -1)
{
from.Send(new PlaySound(liftSound, from));
}
from.SendSound(item.GetLiftSound(from));
from.NextActionTime = Core.TickCount + ActionDelay;
@ -7319,22 +7314,21 @@ namespace Server
eable.Free();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SendSound(int soundID)
{
if (soundID != -1 && m_NetState != null)
{
Send(new PlaySound(soundID, this));
}
m_NetState?.SendSoundEffect(soundID, this);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SendSound(int soundID, IPoint3D p)
{
if (soundID != -1 && m_NetState != null)
{
Send(new PlaySound(soundID, p));
}
m_NetState?.SendSoundEffect(soundID, p);
}
/**
* Plays a sound to netstates that can see this mobile
*/
public void PlaySound(int soundID)
{
if (soundID == -1 || m_Map == null)
@ -7342,7 +7336,8 @@ namespace Server
return;
}
var p = Packet.Acquire(new PlaySound(soundID, this));
Span<byte> buffer = stackalloc byte[OutgoingEffectPackets.SoundPacketLength];
OutgoingEffectPackets.CreateSoundEffect(ref buffer, soundID, this);
var eable = m_Map.GetClientsInRange(m_Location);
@ -7350,12 +7345,10 @@ namespace Server
{
if (state.Mobile.CanSee(this))
{
state.Send(p);
state.Send(buffer);
}
}
Packet.Release(p);
eable.Free();
}
@ -7382,12 +7375,7 @@ namespace Server
DisruptiveAction(); // Anything that unhides you will also distrupt meditation
}
public void SendRemovePacket()
{
SendRemovePacket(true);
}
public void SendRemovePacket(bool everyone)
public void SendRemovePacket(bool everyone = true)
{
if (m_Map == null)
{
@ -7530,7 +7518,7 @@ namespace Server
if (m.IsDeadBondedPet)
{
ns.Send(new BondedStatus(m.Serial, true));
ns.SendBondedStatus(m.Serial, true);
}
if (ObjectPropertyList.Enabled)
@ -7690,7 +7678,7 @@ namespace Server
if (IsDeadBondedPet)
{
state.Send(new BondedStatus(Serial, true));
state.SendBondedStatus(Serial, true);
}
if (ObjectPropertyList.Enabled)
@ -7976,7 +7964,7 @@ namespace Server
if (IsDeadBondedPet)
{
m.m_NetState.Send(new BondedStatus(Serial, true));
m.m_NetState.SendBondedStatus(Serial, true);
}
if (ObjectPropertyList.Enabled)
@ -8003,7 +7991,7 @@ namespace Server
if (m.IsDeadBondedPet)
{
ourState.Send(new BondedStatus(m.Serial, true));
ourState.SendBondedStatus(m.Serial, true);
}
if (ObjectPropertyList.Enabled)
@ -8038,7 +8026,7 @@ namespace Server
if (IsDeadBondedPet)
{
ns.Send(new BondedStatus(Serial, true));
ns.SendBondedStatus(Serial, true);
}
if (ObjectPropertyList.Enabled)
@ -8126,7 +8114,7 @@ namespace Server
if (IsDeadBondedPet)
{
state.Send(new BondedStatus(Serial, true));
state.SendBondedStatus(Serial, true);
}
if (ObjectPropertyList.Enabled)

View file

@ -377,7 +377,34 @@ namespace Server.Network
return !(result.IsClosed || result.Length <= 0);
}
public virtual void Send(ref CircularBuffer<byte> buffer, int length)
public void Send(ReadOnlySpan<byte> span)
{
var length = span.Length;
if (Connection == null || BlockAllPackets || length <= 0 || !GetSendBuffer(out var buffer))
{
return;
}
try
{
buffer.CopyFrom(span);
_packetEncoder?.Invoke(ref buffer, ref length);
SendPipe.Writer.Advance((uint)length);
}
catch (Exception ex)
{
#if DEBUG
Console.WriteLine(ex);
TraceException(ex);
#endif
Dispose();
}
}
/**
* Send data using a circular buffer from SendPipe
*/
public void Send(ref CircularBuffer<byte> buffer, int length)
{
if (Connection == null || BlockAllPackets || length <= 0)
{

View file

@ -27,19 +27,6 @@ namespace Server.Network
}
}
public sealed class BondedStatus : Packet
{
public BondedStatus(Serial serial, bool bonded) : base(0xBF)
{
EnsureCapacity(11);
Stream.Write((short)0x19);
Stream.Write((byte)0);
Stream.Write(serial);
Stream.Write((byte)(bonded ? 1 : 0));
}
}
public sealed class MobileMoving : Packet
{
public MobileMoving(Mobile m, int noto) : base(0x77, 17)

View file

@ -32,7 +32,7 @@ namespace Server.Network
writer.Write(attacker);
writer.Write(defender);
ns.Send(ref buffer, 10);
ns.Send(ref buffer, writer.Position);
}
public static void SendSetWarMode(this NetState ns, bool warmode)
@ -47,7 +47,7 @@ namespace Server.Network
// Warmode, 0x00, 0x32, 0x00
writer.Write(warmode ? 0x01003200 : 0x00003200);
ns.Send(ref buffer, 5);
ns.Send(ref buffer, writer.Position);
}
public static void SendChangeCombatant(this NetState ns, Serial combatant)
@ -61,7 +61,7 @@ namespace Server.Network
writer.Write((byte)0xAA); // Packet ID
writer.Write(combatant);
ns.Send(ref buffer, 5);
ns.Send(ref buffer, writer.Position);
}
}
}

View file

@ -0,0 +1,331 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingEffectPackets.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Buffers;
namespace Server.Network
{
public static class OutgoingEffectPackets
{
public const int SoundPacketLength = 12;
public const int ParticleEffectLength = 49;
public const int HuedEffectLength = 36;
public const int BoltEffectLength = 36;
public static void CreateSoundEffect(ref Span<byte> buffer, int soundID, IPoint3D target)
{
var writer = new SpanWriter(buffer);
writer.Write((byte)0x54); // Packet ID
writer.Write((byte)1); // flags
writer.Write((short)soundID);
writer.Write((short)0); // volume
writer.Write((short)target.X);
writer.Write((short)target.Y);
writer.Write((short)target.Z);
}
public static void SendSoundEffect(this NetState ns, int soundID, IPoint3D target)
{
if (ns == null || !ns.GetSendBuffer(out var buffer))
{
return;
}
var writer = new CircularBufferWriter(buffer);
writer.Write((byte)0x54); // Packet ID
writer.Write((byte)1); // flags
writer.Write((short)soundID);
writer.Write((short)0); // volume
writer.Write((short)target.X);
writer.Write((short)target.Y);
writer.Write((short)target.Z);
ns.Send(ref buffer, writer.Position);
}
public static void CreateParticleEffect(
ref Span<byte> buffer,
EffectType type, Serial from, Serial to, int itemID, IPoint3D fromPoint, IPoint3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode, int effect,
int explodeEffect, int explodeSound, Serial serial, int layer, int unknown
)
{
var writer = new SpanWriter(buffer);
writer.Write((byte)0xC7); // Packet ID
writer.Write((byte)type);
writer.Write(from);
writer.Write(to);
writer.Write((short)itemID);
writer.Write((short)fromPoint.X);
writer.Write((short)fromPoint.Y);
writer.Write((sbyte)fromPoint.Z);
writer.Write((short)toPoint.X);
writer.Write((short)toPoint.Y);
writer.Write((sbyte)toPoint.Z);
writer.Write((byte)speed);
writer.Write((byte)duration);
writer.Write((byte)0);
writer.Write((byte)0);
writer.Write(fixedDirection);
writer.Write(explode);
writer.Write(hue);
writer.Write(renderMode);
writer.Write((short)effect);
writer.Write((short)explodeEffect);
writer.Write((short)explodeSound);
writer.Write(serial);
writer.Write((byte)layer);
writer.Write((short)unknown);
}
public static void CreateTargetParticleEffect(
ref Span<byte> buffer,
IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect, int layer, int unknown
) => CreateParticleEffect(
ref buffer,
EffectType.FixedFrom,
e.Serial,
Serial.Zero,
itemID,
e.Location,
e.Location,
speed,
duration,
true,
false,
hue,
renderMode,
effect,
1,
0,
e.Serial,
layer,
unknown
);
public static void CreateLocationParticleEffect(
ref Span<byte> buffer,
IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect, int unknown
) => CreateParticleEffect(
ref buffer,
EffectType.FixedXYZ,
e.Serial,
Serial.Zero,
itemID,
e.Location,
e.Location,
speed,
duration,
true,
false,
hue,
renderMode,
effect,
1,
0,
e.Serial,
255,
unknown
);
public static void CreateMovingParticleEffect(
ref Span<byte> buffer,
IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection,
bool explodes, int hue, int renderMode, int effect, int explodeEffect, int explodeSound, EffectLayer layer,
int unknown
) => CreateParticleEffect(
ref buffer,
EffectType.Moving,
from.Serial,
to.Serial,
itemID,
from.Location,
to.Location,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode,
effect,
explodeEffect,
explodeSound,
Serial.Zero,
(int)layer,
unknown
);
public static void CreateHuedEffect(
ref Span<byte> buffer,
EffectType type, Serial from, Serial to, int itemID, Point3D fromPoint, Point3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode
)
{
var writer = new SpanWriter(buffer);
writer.Write((byte)0xC0); // Packet ID
writer.Write((byte)type);
writer.Write(from);
writer.Write(to);
writer.Write((short)itemID);
writer.Write((short)fromPoint.X);
writer.Write((short)fromPoint.Y);
writer.Write((sbyte)fromPoint.Z);
writer.Write((short)toPoint.X);
writer.Write((short)toPoint.Y);
writer.Write((sbyte)toPoint.Z);
writer.Write((byte)speed);
writer.Write((byte)duration);
writer.Write((byte)0);
writer.Write((byte)0);
writer.Write(fixedDirection);
writer.Write(explode);
writer.Write(hue);
writer.Write(renderMode);
}
public static void CreateTargetHuedEffect(
ref Span<byte> buffer,
IEntity e, int itemID, int speed, int duration, int hue, int renderMode
) => CreateHuedEffect(
ref buffer,
EffectType.FixedFrom,
e.Serial,
Serial.Zero,
itemID,
e.Location,
e.Location,
speed,
duration,
true,
false,
hue,
renderMode
);
public static void CreateLocationHuedEffect(
ref Span<byte> buffer,
Point3D p, int itemID, int speed, int duration, int hue, int renderMode
) => CreateHuedEffect(
ref buffer,
EffectType.FixedXYZ,
Serial.Zero,
Serial.Zero,
itemID,
p,
p,
speed,
duration,
true,
false,
hue,
renderMode
);
public static void CreateMovingHuedEffect(
ref Span<byte> buffer,
IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection,
bool explodes, int hue, int renderMode
) => CreateHuedEffect(
ref buffer,
EffectType.Moving,
from.Serial,
to.Serial,
itemID,
from.Location,
to.Location,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
);
public static void CreateMovingHuedEffect(
ref Span<byte> buffer,
int itemID, Point3D fromLocation, Point3D toLocation, int speed, int duration,
bool fixedDirection, bool explodes, int hue, int renderMode
) => CreateHuedEffect(
ref buffer,
EffectType.Moving,
Serial.Zero,
Serial.Zero,
itemID,
fromLocation,
toLocation,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
);
public static void CreateMovingHuedEffect(
ref Span<byte> buffer,
Serial from, Serial to, int itemID, Point3D fromLocation, Point3D toLocation, int speed, int duration,
bool fixedDirection, bool explodes, int hue, int renderMode
) => CreateHuedEffect(
ref buffer,
EffectType.Moving,
from,
to,
itemID,
fromLocation,
toLocation,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
);
public static void CreateBoltEffect(ref Span<byte> buffer, IEntity target, int hue) => CreateHuedEffect(
ref buffer,
EffectType.Lightning,
target.Serial,
Serial.Zero,
0,
target.Location,
target.Location,
0,
0,
false,
false,
hue,
0
);
public static void SendScreenEffect(this NetState ns, ScreenEffectType type)
{
if (ns == null || !ns.GetSendBuffer(out var buffer))
{
return;
}
var writer = new CircularBufferWriter(buffer);
writer.Write((byte)0x70); // Packet ID
writer.Write((byte)0x4);
writer.Clear(8);
writer.Write((ushort)type);
writer.Clear(16);
ns.Send(ref buffer, writer.Position);
}
}
}

View file

@ -0,0 +1,54 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: OutgoingMobilePackets.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Buffers;
namespace Server.Network
{
public static class OutgoingMobilePackets
{
public const int BondedStatusPacketLength = 11;
public static void CreateBondedStatus(ref Span<byte> buffer, Serial serial, bool bonded)
{
var writer = new SpanWriter(buffer);
writer.Write((byte)0xBF); // Packet ID
writer.Write((ushort)11); // Length
writer.Write((ushort)0x19); // Subpacket ID
writer.Write((byte)0); // Command
writer.Write(serial);
writer.Write(bonded);
}
public static void SendBondedStatus(this NetState ns, Serial serial, bool bonded)
{
if (ns == null || !ns.GetSendBuffer(out var buffer))
{
return;
}
var writer = new CircularBufferWriter(buffer);
writer.Write((byte)0xBF); // Packet ID
writer.Write((ushort)11); // Length
writer.Write((ushort)0x19); // Subpacket ID
writer.Write((byte)0); // Command
writer.Write(serial);
writer.Write(bonded);
ns.Send(ref buffer, writer.Position);
}
}
}

View file

@ -14,6 +14,7 @@
*************************************************************************/
using System;
using Server.HuePickers;
namespace Server.Network
{
@ -305,19 +306,6 @@ namespace Server.Network
}
}
public sealed class PlaySound : Packet
{
public PlaySound(int soundID, IPoint3D target) : base(0x54, 12)
{
Stream.Write((byte)1); // flags
Stream.Write((short)soundID);
Stream.Write((short)0); // volume
Stream.Write((short)target.X);
Stream.Write((short)target.Y);
Stream.Write((short)target.Z);
}
}
public sealed class PlayMusic : Packet
{
public static readonly Packet InvalidInstance = SetStatic(new PlayMusic(MusicName.Invalid));
@ -430,4 +418,14 @@ namespace Server.Network
Stream.Write((short)0x21);
}
}
public sealed class DisplayHuePicker : Packet
{
public DisplayHuePicker(HuePicker huePicker) : base(0x95, 9)
{
Stream.Write(huePicker.Serial);
Stream.Write((short)0);
Stream.Write((short)huePicker.ItemID);
}
}
}

View file

@ -394,7 +394,7 @@ namespace Server.Commands.Generic
index,
CommandLogging.Format(mob)
);
mob.Send(new PlaySound(index, mob.Location));
mob.SendSound(index);
}
else
{

View file

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Server.Commands.Generic;
@ -420,19 +421,16 @@ namespace Server.Commands
toAll
);
Packet p = new PlaySound(index, m.Location);
p.Acquire();
Span<byte> buffer = stackalloc byte[OutgoingEffectPackets.SoundPacketLength];
OutgoingEffectPackets.CreateSoundEffect(ref buffer, index, m);
foreach (var state in m.GetClientsInRange(12))
{
if (toAll || state.Mobile.CanSee(m))
{
state.Send(p);
state.Send(buffer);
}
}
p.Release();
}
[Usage("Echo <text>")]

View file

@ -49,8 +49,7 @@ namespace Server.ContextMenus
book.Content |= (ulong)1 << val;
m_Scroll.Consume();
from.Send(new PlaySound(0x249, book.GetWorldLocation()));
from.SendSound(0x249, book.GetWorldLocation());
}
}
}

View file

@ -476,14 +476,14 @@ namespace Server.Engines.Doom
}
}
public static void PlayEffect(IEntity from, IEntity to, int itemid, int speed, bool explodes)
private static void PlayEffect(IEntity from, IEntity to, int itemid, int speed, bool explodes)
{
Effects.SendMovingParticles(from, to, itemid, speed, 0, true, explodes, 2, 0, 0);
}
public static void SendLocationEffect(IPoint3D p, int itemID, int speed, int duration, int hue)
private static void SendLocationEffect(Point3D p, int itemID, int speed, int duration, int hue)
{
Effects.SendPacket(p, Map.Malas, new LocationEffect(p, itemID, speed, duration, hue, 0));
Effects.SendLocationEffect(p, Map.Malas, itemID, speed, duration, hue);
}
public static void PlayerSendASCII(Mobile player, int index)

View file

@ -68,7 +68,7 @@ namespace Server.Ethics.Evil
{
SpellHelper.Turn(from.Mobile, p);
Effects.PlaySound(p, from.Mobile.Map, 0x1FB);
Effects.PlaySound(new Point3D(p), from.Mobile.Map, 0x1FB);
from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You curse the area.");

View file

@ -68,7 +68,7 @@ namespace Server.Ethics.Hero
{
SpellHelper.Turn(from.Mobile, p);
Effects.PlaySound(p, from.Mobile.Map, 0x299);
Effects.PlaySound(new Point3D(p), from.Mobile.Map, 0x299);
from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You consecrate the area.");

View file

@ -330,7 +330,7 @@ namespace Server.Items
{
case 0:
{
Effects.SendLocationEffect(to, to.Map, 0x113A, 20, 10);
Effects.SendLocationEffect(to, 0x113A, 20);
to.PlaySound(0x231);
to.LocalOverheadMessage(MessageType.Regular, 0x44, 1010523); // A toxic vapor envelops thee.
@ -340,7 +340,7 @@ namespace Server.Items
}
case 1:
{
Effects.SendLocationEffect(to, to.Map, 0x3709, 30);
Effects.SendLocationEffect(to, 0x3709, 30);
to.PlaySound(0x54);
to.LocalOverheadMessage(MessageType.Regular, 0xEE, 1010524); // Searing heat scorches thy skin.

View file

@ -157,24 +157,7 @@ namespace Server.Engines.Quests.Necro
var hue = Utility.RandomList(0x481, 0x482, 0x489, 0x497, 0x66D);
Effects.SendPacket(
from,
map,
new HuedEffect(
EffectType.Moving,
Serial.Zero,
Serial.Zero,
0x36D4,
from,
to,
0,
0,
false,
true,
hue,
0
)
);
Effects.SendMovingEffect(map, 0x36D4, from, to,0, 0, false, true, hue);
}
}

View file

@ -66,7 +66,7 @@ namespace Server.Engines.Quests.Haven
public override bool HandlesOnMovement => Canoneer?.Deleted == false && Canoneer.Active;
public void DoFireEffect(IPoint3D target)
public void DoFireEffect(Point3D target)
{
var from = CannonDirection switch
{
@ -85,7 +85,7 @@ namespace Server.Engines.Quests.Haven
public void Fire(Mobile from, Mobile target)
{
DoFireEffect(target);
DoFireEffect(target.Location);
target.Damage(9999, from);
}

View file

@ -67,7 +67,7 @@ namespace Server.Items
Location = new Point3D(X - Offset.X, Y - Offset.Y, Z - Offset.Z);
}
Effects.PlaySound(this, Map, m_Open ? OpenedSound : ClosedSound);
Effects.PlaySound(this, m_Open ? OpenedSound : ClosedSound);
if (m_Open)
{

View file

@ -81,24 +81,21 @@ namespace Server.Items
{
if (dropped is BasePiece piece && piece.Board == this && base.OnDragDropInto(from, dropped, point))
{
Packet p = new PlaySound(0x127, GetWorldLocation());
p.Acquire();
if (RootParent == from)
{
from.Send(p);
from.SendSound(0x127, GetWorldLocation());
}
else
{
Span<byte> buffer = stackalloc byte[OutgoingEffectPackets.SoundPacketLength];
OutgoingEffectPackets.CreateSoundEffect(ref buffer, 0x127, GetWorldLocation());
foreach (var state in GetClientsInRange(2))
{
state.Send(p);
state.Send(buffer);
}
}
p.Release();
return true;
}

View file

@ -886,7 +886,7 @@ namespace Server.Items
m_Chest.Z++;
}
Effects.PlaySound(m_Chest, m_Map, 0x33B);
Effects.PlaySound(m_Chest.Location, m_Map, 0x33B);
}
if (m_Chest?.Location.Z >= m_Location.Z)

View file

@ -180,7 +180,7 @@ namespace Server.Items
{
if (from.AccessLevel == AccessLevel.Player || !from.Hidden)
{
from.Send(new PlaySound(0x20E, from.Location));
from.SendSound(0x20E, from);
}
from.CloseGump<MoongateConfirmGump>();

View file

@ -414,7 +414,7 @@ namespace Server.Items
rune.Delete();
from.Send(new PlaySound(0x42, GetWorldLocation()));
from.SendSound(0x42, GetWorldLocation());
from.SendMessage((rune.Description?.Trim()).DefaultIfNullOrEmpty("(indescript)"));
@ -432,7 +432,7 @@ namespace Server.Items
{
if (CurCharges < MaxCharges)
{
from.Send(new PlaySound(0x249, GetWorldLocation()));
from.SendSound(0x249, GetWorldLocation());
var amount = dropped.Amount;

View file

@ -591,7 +591,7 @@ namespace Server.Items
scroll.Delete();
from.Send(new PlaySound(0x249, GetWorldLocation()));
from.SendSound(0x249, GetWorldLocation());
return true;
}
}

View file

@ -58,7 +58,7 @@ namespace Server.Items
}
}
public void Use(Mobile from, IPoint3D loc)
public void Use(Mobile from, Point3D loc)
{
if (!CheckUse(from))
{
@ -84,23 +84,14 @@ namespace Server.Items
from.Backpack.ConsumeUpTo(typeof(SulfurousAsh), sulfAsh);
from.PlaySound(0x15F);
Effects.SendPacket(
Effects.SendMovingEffect(
from,
from.Map,
new HuedEffect(
EffectType.Moving,
from.Serial,
Serial.Zero,
0x36D4,
from.Location,
loc,
5,
0,
false,
true,
0,
0
)
loc,
0x36D4,
5,
0,
false,
true
);
var eable = from.Map.GetMobilesInRange(new Point3D(loc), 2);
@ -241,14 +232,14 @@ namespace Server.Items
return;
}
IPoint3D loc;
Point3D loc;
if (targeted is Item item)
{
loc = item.GetWorldLocation();
}
else
{
loc = targeted as IPoint3D;
loc = new Point3D(targeted as IPoint3D);
}
m_Horn.Use(from, loc);

View file

@ -214,11 +214,11 @@ namespace Server.Items
}
}
public void DoFireEffect(IPoint3D target)
public void DoFireEffect(Point3D target)
{
var map = Map;
if (target == null || map == null)
if (map == null)
{
return;
}
@ -228,7 +228,7 @@ namespace Server.Items
for (var count = Utility.Random(3); count > 0; count--)
{
IPoint3D location = new Point3D(
Point3D location = new Point3D(
target.X + Utility.RandomMinMax(-1, 1),
target.Y + Utility.RandomMinMax(-1, 1),
target.Z
@ -320,9 +320,11 @@ namespace Server.Items
break;
}
if (allow && Utility.InRange(new Point3D(p), m_Cannon.Location, 14))
var loc = new Point3D(p);
if (allow && Utility.InRange(loc, m_Cannon.Location, 14))
{
m_Cannon.DoFireEffect(p);
m_Cannon.DoFireEffect(loc);
}
else
{

View file

@ -408,7 +408,7 @@ namespace Server.Items
20,
5042
);
Effects.PlaySound(m_Creature, m_Creature.Map, 0x201);
Effects.PlaySound(m_Creature, 0x201);
m_Creature.Delete();
}

View file

@ -58,7 +58,8 @@ namespace Server.Mobiles
20,
5042
);
Effects.PlaySound(m_Mobile, m_Mobile.Map, 0x201);
Effects.PlaySound(m_Mobile,0x201);
m_Mobile.Delete();
}
@ -405,13 +406,13 @@ namespace Server.Mobiles
/*
// An area attack that only damages staff, wtf?
private DateTime m_NextWave;
public void AreaHeatDamage()
{
Mobile mob = ControlMaster;
if (mob != null)
{
if (mob.InRange( Location, 2 ))
@ -422,9 +423,9 @@ namespace Server.Mobiles
mob.SendLocalizedMessage( 1008112 ); // The intense heat is damaging you!
}
}
GuardedRegion r = Region as GuardedRegion;
if (r != null && mob.Alive)
{
foreach ( Mobile m in GetMobilesInRange( 2 ) )
@ -434,7 +435,7 @@ namespace Server.Mobiles
}
}
}
m_NextWave = DateTime.UtcNow + TimeSpan.FromSeconds( 3 );
}
*/

View file

@ -3550,7 +3550,7 @@ namespace Server.Items
20,
5042
);
Effects.PlaySound(defender, defender.Map, 0x201);
Effects.PlaySound(defender, 0x201);
defender.Delete();
}

View file

@ -2278,7 +2278,7 @@ namespace Server.Mobiles
20,
5042
);
Effects.PlaySound(m, m.Map, 0x201);
Effects.PlaySound(m, 0x201);
m.Delete();
}
@ -3216,12 +3216,7 @@ namespace Server.Mobiles
if (IsBonded)
{
var sound = GetDeathSound();
if (sound >= 0)
{
Effects.PlaySound(this, Map, sound);
}
Effects.PlaySound(this, GetDeathSound());
Warmode = false;
@ -3845,7 +3840,9 @@ namespace Server.Mobiles
IsDeadPet = false;
Effects.SendPacket(Location, Map, new BondedStatus(Serial, false));
Span<byte> buffer = stackalloc byte[OutgoingMobilePackets.BondedStatusPacketLength];
OutgoingMobilePackets.CreateBondedStatus(ref buffer, Serial, false);
Effects.SendPacket(Location, Map, ref buffer);
SendIncomingPacket();
SendIncomingPacket();

View file

@ -103,8 +103,8 @@ namespace Server.Mobiles
LootPack.FilthyRich.Generate(this, rm.Backpack, false, LootPack.GetLuckChanceForKiller(this));
}
Effects.PlaySound(this, Map, GetDeathSound());
Effects.SendLocationEffect(Location, Map, 0x3709, 30, 10, 0x835, 0);
Effects.PlaySound(this, GetDeathSound());
Effects.SendLocationEffect(Location, Map, 0x3709, 30, 10, 0x835);
rm.MoveToWorld(Location, Map);
Delete();

View file

@ -112,7 +112,7 @@ namespace Server.Mobiles
LootPack.FilthyRich.Generate(this, rm.Backpack, false, LootPack.GetLuckChanceForKiller(this));
}
Effects.PlaySound(this, Map, GetDeathSound());
Effects.PlaySound(this, GetDeathSound());
Effects.SendLocationEffect(Location, Map, 0x3709, 30, 10, 0x835, 0);
rm.MoveToWorld(Location, Map);

View file

@ -78,68 +78,42 @@ namespace Server.Mobiles
* Effect: damage is dealt to the attacker, no damage is taken by the fan dancer
*/
private void ThrowFan(Mobile to)
{
if (!(Utility.RandomDouble() < 0.8) || to.InRange(this, 1))
{
return;
}
/* Fan Throw
* Effect: - To: "0x57D4F5B" - ItemId: "0x27A3" - ItemIdName: "Tessen" - FromLocation: "(992 299, 24)" - ToLocation: "(992 308, 22)" - Speed: "10" - Duration: "0" - FixedDirection: "False" - Explode: "False" - Hue: "0x0" - Render: "0x0"
* Damage: 50-65
*/
Effects.SendMovingEffect(
to.Location,
to.Map,
0x27A3,
Location,
to.Location,
10,
0,
false,
false
);
AOS.Damage(to, this, Utility.RandomMinMax(50, 65), 100, 0, 0, 0, 0);
}
public override void OnDamagedBySpell(Mobile attacker)
{
base.OnDamagedBySpell(attacker);
if (Utility.RandomDouble() < 0.8 && !attacker.InRange(this, 1))
{
/* Fan Throw
* Effect: - To: "0x57D4F5B" - ItemId: "0x27A3" - ItemIdName: "Tessen" - FromLocation: "(992 299, 24)" - ToLocation: "(992 308, 22)" - Speed: "10" - Duration: "0" - FixedDirection: "False" - Explode: "False" - Hue: "0x0" - Render: "0x0"
* Damage: 50-65
*/
Effects.SendPacket(
attacker,
attacker.Map,
new HuedEffect(
EffectType.Moving,
Serial.Zero,
Serial.Zero,
0x27A3,
Location,
attacker.Location,
10,
0,
false,
false,
0,
0
)
);
AOS.Damage(attacker, this, Utility.RandomMinMax(50, 65), 100, 0, 0, 0, 0);
}
ThrowFan(attacker);
}
public override void OnGotMeleeAttack(Mobile attacker)
{
base.OnGotMeleeAttack(attacker);
if (Utility.RandomDouble() < 0.8 && !attacker.InRange(this, 1))
{
/* Fan Throw
* Effect: - To: "0x57D4F5B" - ItemId: "0x27A3" - ItemIdName: "Tessen" - FromLocation: "(992 299, 24)" - ToLocation: "(992 308, 22)" - Speed: "10" - Duration: "0" - FixedDirection: "False" - Explode: "False" - Hue: "0x0" - Render: "0x0"
* Damage: 50-65
*/
Effects.SendPacket(
attacker,
attacker.Map,
new HuedEffect(
EffectType.Moving,
Serial.Zero,
Serial.Zero,
0x27A3,
Location,
attacker.Location,
10,
0,
false,
false,
0,
0
)
);
AOS.Damage(attacker, this, Utility.RandomMinMax(50, 65), 100, 0, 0, 0, 0);
}
ThrowFan(attacker);
}
public override void OnGaveMeleeAttack(Mobile defender)
@ -158,9 +132,8 @@ namespace Server.Mobiles
* Effect does not stack
*/
defender.SendLocalizedMessage(
1070833
); // The creature fans you with fire, reducing your resistance to fire attacks.
// The creature fans you with fire, reducing your resistance to fire attacks.
defender.SendLocalizedMessage(1070833);
var effect = -(defender.FireResistance / 10);

View file

@ -355,7 +355,7 @@ namespace Server.Mobiles
30,
5052
);
Effects.PlaySound(g, g.Map, 0x208);
Effects.PlaySound(g, 0x208);
break;
}
@ -368,7 +368,7 @@ namespace Server.Mobiles
10,
5044
);
Effects.PlaySound(g, g.Map, 0x307);
Effects.PlaySound(g, 0x307);
break;
}

View file

@ -687,7 +687,7 @@ namespace Server.Mobiles
30,
5052
);
Effects.PlaySound(g, g.Map, 0x208);
Effects.PlaySound(g, 0x208);
break;
}
@ -700,7 +700,7 @@ namespace Server.Mobiles
10,
5044
);
Effects.PlaySound(g, g.Map, 0x307);
Effects.PlaySound(g, 0x307);
break;
}

View file

@ -67,7 +67,7 @@ namespace Server.Spells.Chivalry
20,
5042
);
Effects.PlaySound(m, m.Map, 0x201);
Effects.PlaySound(m, 0x201);
m.Delete();
continue;

View file

@ -62,7 +62,7 @@ namespace Server.Spells.Fifth
eastToWest = false;
}
Effects.PlaySound(p, Caster.Map, 0x20B);
Effects.PlaySound(new Point3D(p), Caster.Map, 0x20B);
var itemID = eastToWest ? 0x3915 : 0x3922;

View file

@ -43,6 +43,7 @@ namespace Server.Spells.Fourth
var map = Caster.Map;
var directTarget = p as Mobile;
var loc = new Point3D(p);
if (map != null)
{
@ -54,13 +55,13 @@ namespace Server.Spells.Fourth
targets.Add(directTarget);
}
var eable = map.GetMobilesInRange(new Point3D(p), 2);
var eable = map.GetMobilesInRange(loc, 2);
targets.AddRange(eable.Where(m => m != directTarget).Where(m => AreaCanTarget(m, feluccaRules)));
eable.Free();
}
Effects.PlaySound(p, Caster.Map, 0x299);
Effects.PlaySound(loc, Caster.Map, 0x299);
if (targets.Count > 0)
{

View file

@ -40,9 +40,11 @@ namespace Server.Spells.Fourth
SpellHelper.GetSurfaceTop(ref p);
var loc = new Point3D(p);
if (!Core.AOS)
{
Effects.PlaySound(p, Caster.Map, 0x299);
Effects.PlaySound(loc, Caster.Map, 0x299);
}
if (Caster.Map == null)
@ -51,7 +53,7 @@ namespace Server.Spells.Fourth
return;
}
var targets = Caster.Map.GetMobilesInRange(new Point3D(p), Core.AOS ? 2 : 3)
var targets = Caster.Map.GetMobilesInRange(loc, Core.AOS ? 2 : 3)
.Where(m => Caster.CanBeBeneficial(m, false));
if (Core.AOS)

View file

@ -62,7 +62,7 @@ namespace Server.Spells.Fourth
eastToWest = false;
}
Effects.PlaySound(p, Caster.Map, 0x20C);
Effects.PlaySound(new Point3D(p), Caster.Map, 0x20C);
var itemID = eastToWest ? 0x398C : 0x3996;

View file

@ -51,9 +51,11 @@ namespace Server.Spells.Mysticism
if (map != null)
{
PlayEffect(p, Caster.Map);
var loc = new Point3D(p);
foreach (var m in map.GetMobilesInRange(new Point3D(p), 2))
PlayEffect(loc, Caster.Map);
foreach (var m in map.GetMobilesInRange(loc, 2))
{
if (m == Caster)
{
@ -94,7 +96,7 @@ namespace Server.Spells.Mysticism
Caster.Target = new SpellTargetPoint3D(this);
}
private static void PlayEffect(IPoint3D p, Map map)
private static void PlayEffect(Point3D p, Map map)
{
Effects.PlaySound(p, map, 0x64F);
@ -105,7 +107,7 @@ namespace Server.Spells.Mysticism
PlaySingleEffect(p, map, -1, 1, 1, 3);
}
private static void PlaySingleEffect(IPoint3D p, Map map, int a, int b, int c, int d)
private static void PlaySingleEffect(Point3D p, Map map, int a, int b, int c, int d)
{
int x = p.X, y = p.Y, z = p.Z + 18;
@ -120,25 +122,20 @@ namespace Server.Spells.Mysticism
SendEffectPacket(p, map, new Point3D(x + a, y + c, z), new Point3D(x + a, y + d, z));
}
private static void SendEffectPacket(IPoint3D p, Map map, Point3D orig, Point3D dest)
private static void SendEffectPacket(Point3D p, Map map, Point3D orig, Point3D dest)
{
Effects.SendPacket(
Effects.SendMovingEffect(
p,
map,
new HuedEffect(
EffectType.Moving,
Serial.Zero,
Serial.Zero,
0x36D4,
orig,
dest,
0,
0,
false,
false,
0x63,
0x4
)
0x36D4,
orig,
dest,
0,
0,
false,
false,
0x63,
0x4
);
}
}

View file

@ -54,9 +54,11 @@ namespace Server.Spells.Mysticism
if (map != null)
{
PlayEffect(p, Caster.Map);
var loc = new Point3D(p);
foreach (var m in map.GetMobilesInRange(new Point3D(p), 2))
PlayEffect(loc, Caster.Map);
foreach (var m in map.GetMobilesInRange(loc, 2))
{
if (m == Caster)
{
@ -103,7 +105,7 @@ namespace Server.Spells.Mysticism
Caster.Target = new SpellTargetPoint3D(this);
}
private static void PlayEffect(IPoint3D p, Map map)
private static void PlayEffect(Point3D p, Map map)
{
Effects.PlaySound(p, map, 0x64F);
@ -114,7 +116,7 @@ namespace Server.Spells.Mysticism
PlaySingleEffect(p, map, -1, 1, 1, 3);
}
private static void PlaySingleEffect(IPoint3D p, Map map, int a, int b, int c, int d)
private static void PlaySingleEffect(Point3D p, Map map, int a, int b, int c, int d)
{
int x = p.X, y = p.Y, z = p.Z + 18;
@ -129,25 +131,20 @@ namespace Server.Spells.Mysticism
SendEffectPacket(p, map, new Point3D(x + a, y + c, z), new Point3D(x + a, y + d, z));
}
private static void SendEffectPacket(IPoint3D p, Map map, Point3D orig, Point3D dest)
private static void SendEffectPacket(Point3D p, Map map, Point3D orig, Point3D dest)
{
Effects.SendPacket(
Effects.SendMovingEffect(
p,
map,
new HuedEffect(
EffectType.Moving,
Serial.Zero,
Serial.Zero,
0x375A,
orig,
dest,
0,
0,
false,
false,
0x49A,
0x4
)
0x375A,
orig,
dest,
0,
0,
false,
false,
0x49A,
0x4
);
}
}

View file

@ -62,7 +62,7 @@ namespace Server.Spells.Seventh
eastToWest = false;
}
Effects.PlaySound(p, Caster.Map, 0x20B);
Effects.PlaySound(new Point3D(p), Caster.Map, 0x20B);
TimeSpan duration;

View file

@ -60,7 +60,7 @@ namespace Server.Spells.Seventh
20,
5042
);
Effects.PlaySound(bc, bc.Map, 0x201);
Effects.PlaySound(bc, 0x201);
bc.Delete();
}

View file

@ -46,10 +46,11 @@ namespace Server.Spells.Seventh
var map = Caster.Map;
var playerVsPlayer = false;
var loc = new Point3D(p);
if (map != null)
{
var eable = map.GetMobilesInRange(new Point3D(p), 2);
var eable = map.GetMobilesInRange(loc, 2);
targets = eable.Where(
m =>
@ -86,7 +87,7 @@ namespace Server.Spells.Seventh
if (targets.Count > 0)
{
Effects.PlaySound(p, Caster.Map, 0x160);
Effects.PlaySound(loc, Caster.Map, 0x160);
if (Core.AOS && targets.Count > 2)
{

View file

@ -53,7 +53,7 @@ namespace Server.Spells.Sixth
20,
5042
);
Effects.PlaySound(m, m.Map, 0x201);
Effects.PlaySound(m, 0x201);
m.Delete();
}

View file

@ -63,7 +63,7 @@ namespace Server.Spells.Sixth
rune.Mark(Caster);
Caster.PlaySound(0x1FA);
Effects.SendLocationEffect(Caster, Caster.Map, 14201, 16);
Effects.SendLocationEffect(Caster, 14201, 16);
}
FinishSequence();

View file

@ -61,7 +61,7 @@ namespace Server.Spells.Sixth
eastToWest = false;
}
Effects.PlaySound(p, Caster.Map, 0x20B);
Effects.PlaySound(new Point3D(p), Caster.Map, 0x20B);
var itemID = eastToWest ? 0x3967 : 0x3979;

View file

@ -27,16 +27,17 @@ namespace Server.Spells.Third
if (CheckSequence())
{
SpellHelper.Turn(Caster, p);
var loc = new Point3D(p);
Effects.SendLocationParticles(
EffectItem.Create(new Point3D(p), Caster.Map, EffectItem.DefaultDuration),
EffectItem.Create(loc, Caster.Map, EffectItem.DefaultDuration),
0x376A,
9,
32,
5024
);
Effects.PlaySound(p, Caster.Map, 0x1FF);
Effects.PlaySound(loc, Caster.Map, 0x1FF);
if (p is Mobile)
{

View file

@ -59,7 +59,7 @@ namespace Server.Spells.Third
eastToWest = false;
}
Effects.PlaySound(p, Caster.Map, 0x1F6);
Effects.PlaySound(new Point3D(p), Caster.Map, 0x1F6);
for (var i = -1; i <= 1; ++i)
{