fix(core): Converts mobile stats packets (#360)
- [X] Converts mobile stats packets - [X] Removes human racial from non-players
This commit is contained in:
parent
d73afdba8e
commit
5b69f1d389
10 changed files with 413 additions and 423 deletions
|
|
@ -1,93 +0,0 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using Server.Network;
|
||||
using Xunit;
|
||||
|
||||
namespace Server.Tests.Network
|
||||
{
|
||||
[Collection("Sequential Tests")]
|
||||
public class AttributeNormalizerTests
|
||||
{
|
||||
[Fact]
|
||||
public void TestAttributeNormalizerEnabled()
|
||||
{
|
||||
AttributeNormalizer.Enabled = true;
|
||||
AttributeNormalizer.Maximum = 25;
|
||||
|
||||
var stream = new PacketWriter(4);
|
||||
|
||||
const ushort cur = 50;
|
||||
const ushort max = 100;
|
||||
|
||||
AttributeNormalizer.Write(stream, cur, max);
|
||||
|
||||
Span<byte> expectedData = stackalloc byte[4];
|
||||
var pos = 0;
|
||||
expectedData.Write(ref pos, (ushort)AttributeNormalizer.Maximum);
|
||||
expectedData.Write(ref pos, (ushort)(cur * 25 / max));
|
||||
|
||||
AssertThat.Equal(stream.ToArray(), expectedData);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestAttributeNormalizerReversedEnabled()
|
||||
{
|
||||
AttributeNormalizer.Enabled = true;
|
||||
AttributeNormalizer.Maximum = 25;
|
||||
|
||||
var stream = new PacketWriter(4);
|
||||
|
||||
const ushort cur = 50;
|
||||
const ushort max = 100;
|
||||
|
||||
AttributeNormalizer.WriteReverse(stream, cur, max);
|
||||
|
||||
Span<byte> expectedData = stackalloc byte[4];
|
||||
var pos = 0;
|
||||
expectedData.Write(ref pos, (ushort)(cur * 25 / max));
|
||||
expectedData.Write(ref pos, (ushort)AttributeNormalizer.Maximum);
|
||||
|
||||
AssertThat.Equal(stream.ToArray(), expectedData);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestAttributeNormalizerDisabled()
|
||||
{
|
||||
AttributeNormalizer.Enabled = false;
|
||||
|
||||
var stream = new PacketWriter(4);
|
||||
|
||||
const ushort cur = 50;
|
||||
const ushort max = 100;
|
||||
|
||||
AttributeNormalizer.Write(stream, cur, max);
|
||||
|
||||
Span<byte> expectedData = stackalloc byte[4];
|
||||
var pos = 0;
|
||||
expectedData.Write(ref pos, max);
|
||||
expectedData.Write(ref pos, cur);
|
||||
|
||||
AssertThat.Equal(stream.ToArray(), expectedData);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestAttributeNormalizerReversedDisabled()
|
||||
{
|
||||
AttributeNormalizer.Enabled = false;
|
||||
|
||||
var stream = new PacketWriter(4);
|
||||
|
||||
const ushort cur = 50;
|
||||
const ushort max = 100;
|
||||
|
||||
AttributeNormalizer.WriteReverse(stream, cur, max);
|
||||
|
||||
Span<byte> expectedData = stackalloc byte[4];
|
||||
var pos = 0;
|
||||
expectedData.Write(ref pos, cur);
|
||||
expectedData.Write(ref pos, max);
|
||||
|
||||
AssertThat.Equal(stream.ToArray(), expectedData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -625,17 +625,16 @@ namespace Server.Tests.Network
|
|||
{
|
||||
var m = new Mobile(0x1);
|
||||
m.DefaultMobileInit();
|
||||
m.Str = 100;
|
||||
m.Hits = 100;
|
||||
|
||||
var data = new MobileHits(m).Compile();
|
||||
var expected = new MobileHits(m).Compile();
|
||||
|
||||
Span<byte> expectedData = stackalloc byte[9];
|
||||
var pos = 0;
|
||||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileHits(m);
|
||||
|
||||
expectedData.Write(ref pos, (byte)0xA1); // Packet ID
|
||||
expectedData.Write(ref pos, m.Serial);
|
||||
expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, false);
|
||||
|
||||
AssertThat.Equal(data, expectedData);
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -643,17 +642,16 @@ namespace Server.Tests.Network
|
|||
{
|
||||
var m = new Mobile(0x1);
|
||||
m.DefaultMobileInit();
|
||||
m.Str = 100;
|
||||
m.Hits = 100;
|
||||
|
||||
var data = new MobileHitsN(m).Compile();
|
||||
var expected = new MobileHitsN(m).Compile();
|
||||
|
||||
Span<byte> expectedData = stackalloc byte[9];
|
||||
var pos = 0;
|
||||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileHits(m, true);
|
||||
|
||||
expectedData.Write(ref pos, (byte)0xA1); // Packet ID
|
||||
expectedData.Write(ref pos, m.Serial);
|
||||
expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, true);
|
||||
|
||||
AssertThat.Equal(data, expectedData);
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -661,17 +659,16 @@ namespace Server.Tests.Network
|
|||
{
|
||||
var m = new Mobile(0x1);
|
||||
m.DefaultMobileInit();
|
||||
m.Int = 75;
|
||||
m.Mana = 100;
|
||||
|
||||
var data = new MobileMana(m).Compile();
|
||||
var expected = new MobileMana(m).Compile();
|
||||
|
||||
Span<byte> expectedData = stackalloc byte[9];
|
||||
var pos = 0;
|
||||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileMana(m);
|
||||
|
||||
expectedData.Write(ref pos, (byte)0xA2); // Packet ID
|
||||
expectedData.Write(ref pos, m.Serial);
|
||||
expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, false);
|
||||
|
||||
AssertThat.Equal(data, expectedData);
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -679,17 +676,16 @@ namespace Server.Tests.Network
|
|||
{
|
||||
var m = new Mobile(0x1);
|
||||
m.DefaultMobileInit();
|
||||
m.Int = 75;
|
||||
m.Mana = 100;
|
||||
|
||||
var data = new MobileManaN(m).Compile();
|
||||
var expected = new MobileManaN(m).Compile();
|
||||
|
||||
Span<byte> expectedData = stackalloc byte[9];
|
||||
var pos = 0;
|
||||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileMana(m, true);
|
||||
|
||||
expectedData.Write(ref pos, (byte)0xA2); // Packet ID
|
||||
expectedData.Write(ref pos, m.Serial);
|
||||
expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, true);
|
||||
|
||||
AssertThat.Equal(data, expectedData);
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -697,17 +693,16 @@ namespace Server.Tests.Network
|
|||
{
|
||||
var m = new Mobile(0x1);
|
||||
m.DefaultMobileInit();
|
||||
m.Dex = 75;
|
||||
m.Stam = 100;
|
||||
|
||||
var data = new MobileStam(m).Compile();
|
||||
var expected = new MobileStam(m).Compile();
|
||||
|
||||
Span<byte> expectedData = stackalloc byte[9];
|
||||
var pos = 0;
|
||||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileStam(m);
|
||||
|
||||
expectedData.Write(ref pos, (byte)0xA3); // Packet ID
|
||||
expectedData.Write(ref pos, m.Serial);
|
||||
expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, false);
|
||||
|
||||
AssertThat.Equal(data, expectedData);
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -715,17 +710,16 @@ namespace Server.Tests.Network
|
|||
{
|
||||
var m = new Mobile(0x1);
|
||||
m.DefaultMobileInit();
|
||||
m.Dex = 75;
|
||||
m.Stam = 100;
|
||||
|
||||
var data = new MobileStamN(m).Compile();
|
||||
var expected = new MobileStamN(m).Compile();
|
||||
|
||||
Span<byte> expectedData = stackalloc byte[9];
|
||||
var pos = 0;
|
||||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileStam(m, true);
|
||||
|
||||
expectedData.Write(ref pos, (byte)0xA3); // Packet ID
|
||||
expectedData.Write(ref pos, m.Serial);
|
||||
expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, true);
|
||||
|
||||
AssertThat.Equal(data, expectedData);
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -733,19 +727,20 @@ namespace Server.Tests.Network
|
|||
{
|
||||
var m = new Mobile(0x1);
|
||||
m.DefaultMobileInit();
|
||||
m.Str = 50;
|
||||
m.Hits = 100;
|
||||
m.Int = 75;
|
||||
m.Mana = 100;
|
||||
m.Dex = 25;
|
||||
m.Stam = 100;
|
||||
|
||||
var data = new MobileAttributes(m).Compile();
|
||||
var expected = new MobileAttributes(m).Compile();
|
||||
|
||||
Span<byte> expectedData = stackalloc byte[17];
|
||||
var pos = 0;
|
||||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileAttributes(m);
|
||||
|
||||
expectedData.Write(ref pos, (byte)0x2D); // Packet ID
|
||||
expectedData.Write(ref pos, m.Serial);
|
||||
expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, false);
|
||||
expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, false);
|
||||
expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, false);
|
||||
|
||||
AssertThat.Equal(data, expectedData);
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -753,19 +748,20 @@ namespace Server.Tests.Network
|
|||
{
|
||||
var m = new Mobile(0x1);
|
||||
m.DefaultMobileInit();
|
||||
m.Str = 50;
|
||||
m.Hits = 100;
|
||||
m.Int = 75;
|
||||
m.Mana = 100;
|
||||
m.Dex = 25;
|
||||
m.Stam = 100;
|
||||
|
||||
var data = new MobileAttributesN(m).Compile();
|
||||
var expected = new MobileAttributesN(m).Compile();
|
||||
|
||||
Span<byte> expectedData = stackalloc byte[17];
|
||||
var pos = 0;
|
||||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileAttributes(m, true);
|
||||
|
||||
expectedData.Write(ref pos, (byte)0x2D); // Packet ID
|
||||
expectedData.Write(ref pos, m.Serial);
|
||||
expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, true);
|
||||
expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, true);
|
||||
expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, true);
|
||||
|
||||
AssertThat.Equal(data, expectedData);
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,4 +49,90 @@ namespace Server.Tests.Network
|
|||
Stream.Write((byte)noto);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileHits : Packet
|
||||
{
|
||||
public MobileHits(Mobile m) : base(0xA1, 9)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
Stream.Write((short)m.HitsMax);
|
||||
Stream.Write((short)m.Hits);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileHitsN : Packet
|
||||
{
|
||||
public MobileHitsN(Mobile m) : base(0xA1, 9)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
AttributeNormalizer.Write(Stream, m.Hits, m.HitsMax);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileMana : Packet
|
||||
{
|
||||
public MobileMana(Mobile m) : base(0xA2, 9)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
Stream.Write((short)m.ManaMax);
|
||||
Stream.Write((short)m.Mana);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileManaN : Packet
|
||||
{
|
||||
public MobileManaN(Mobile m) : base(0xA2, 9)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
AttributeNormalizer.Write(Stream, m.Mana, m.ManaMax);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileStam : Packet
|
||||
{
|
||||
public MobileStam(Mobile m) : base(0xA3, 9)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
Stream.Write((short)m.StamMax);
|
||||
Stream.Write((short)m.Stam);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileStamN : Packet
|
||||
{
|
||||
public MobileStamN(Mobile m) : base(0xA3, 9)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
AttributeNormalizer.Write(Stream, m.Stam, m.StamMax);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileAttributes : Packet
|
||||
{
|
||||
public MobileAttributes(Mobile m) : base(0x2D, 17)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
|
||||
Stream.Write((short)m.HitsMax);
|
||||
Stream.Write((short)m.Hits);
|
||||
|
||||
Stream.Write((short)m.ManaMax);
|
||||
Stream.Write((short)m.Mana);
|
||||
|
||||
Stream.Write((short)m.StamMax);
|
||||
Stream.Write((short)m.Stam);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileAttributesN : Packet
|
||||
{
|
||||
public MobileAttributesN(Mobile m) : base(0x2D, 17)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
|
||||
AttributeNormalizer.Write(Stream, m.Hits, m.HitsMax);
|
||||
AttributeNormalizer.Write(Stream, m.Mana, m.ManaMax);
|
||||
AttributeNormalizer.Write(Stream, m.Stam, m.StamMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -622,7 +622,7 @@ namespace Server
|
|||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Race Race
|
||||
{
|
||||
get => m_Race ?? (m_Race = Race.DefaultRace);
|
||||
get => m_Race ??= Race.DefaultRace;
|
||||
set
|
||||
{
|
||||
var oldRace = Race;
|
||||
|
|
@ -1322,15 +1322,7 @@ namespace Server
|
|||
[Hue, CommandProperty(AccessLevel.GameMaster)]
|
||||
public virtual int Hue
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_HueMod != -1)
|
||||
{
|
||||
return m_HueMod;
|
||||
}
|
||||
|
||||
return m_Hue;
|
||||
}
|
||||
get => m_HueMod != -1 ? m_HueMod : m_Hue;
|
||||
set
|
||||
{
|
||||
var oldHue = m_Hue;
|
||||
|
|
@ -2100,7 +2092,6 @@ namespace Server
|
|||
if (Hits < HitsMax)
|
||||
{
|
||||
m_HitsTimer ??= new HitsTimer(this);
|
||||
|
||||
m_HitsTimer.Start();
|
||||
}
|
||||
else if (Hits > HitsMax)
|
||||
|
|
@ -2290,7 +2281,6 @@ namespace Server
|
|||
if (CanRegenHits)
|
||||
{
|
||||
m_HitsTimer ??= new HitsTimer(this);
|
||||
|
||||
m_HitsTimer.Start();
|
||||
}
|
||||
else
|
||||
|
|
@ -2850,7 +2840,7 @@ namespace Server
|
|||
ns.Send(new MobileIncoming(ns, this, this));
|
||||
ns.SendSupportedFeature();
|
||||
ns.Send(new MobileUpdate(this, ns.StygianAbyss));
|
||||
ns.Send(new MobileAttributes(this));
|
||||
ns.SendMobileAttributes(this);
|
||||
}
|
||||
|
||||
OnMapChange(oldMap);
|
||||
|
|
@ -3091,23 +3081,23 @@ namespace Server
|
|||
}
|
||||
else if (sendAll)
|
||||
{
|
||||
ourState.Send(new MobileAttributes(m));
|
||||
ourState.SendMobileAttributes(m);
|
||||
}
|
||||
else if (sendAny)
|
||||
{
|
||||
if (sendHits)
|
||||
{
|
||||
ourState.Send(new MobileHits(m));
|
||||
}
|
||||
|
||||
if (sendStam)
|
||||
{
|
||||
ourState.Send(new MobileStam(m));
|
||||
ourState.SendMobileHits(m);
|
||||
}
|
||||
|
||||
if (sendMana)
|
||||
{
|
||||
ourState.Send(new MobileMana(m));
|
||||
ourState.SendMobileMana(m);
|
||||
}
|
||||
|
||||
if (sendStam)
|
||||
{
|
||||
ourState.SendMobileStam(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3115,15 +3105,15 @@ namespace Server
|
|||
{
|
||||
if (Party is IParty ip)
|
||||
{
|
||||
if (sendStam)
|
||||
{
|
||||
ip.OnStamChanged(this);
|
||||
}
|
||||
|
||||
if (sendMana)
|
||||
{
|
||||
ip.OnManaChanged(this);
|
||||
}
|
||||
|
||||
if (sendStam)
|
||||
{
|
||||
ip.OnStamChanged(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3165,9 +3155,6 @@ namespace Server
|
|||
sendOPLUpdate || sendHair || sendFacialHair || sendHealthbarPoison ||
|
||||
sendHealthbarYellow))
|
||||
{
|
||||
Mobile beholder;
|
||||
|
||||
Packet hitsPacket = null;
|
||||
Packet statPacketTrue = null;
|
||||
Packet statPacketFalse = null;
|
||||
Packet hairPacket = null;
|
||||
|
|
@ -3183,104 +3170,111 @@ namespace Server
|
|||
Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength];
|
||||
removeEntity.InitializePacket();
|
||||
|
||||
Span<byte> hitsPacket = stackalloc byte[OutgoingMobilePackets.MobileAttributePacketLength];
|
||||
hitsPacket.InitializePacket();
|
||||
|
||||
foreach (var state in eable)
|
||||
{
|
||||
beholder = state.Mobile;
|
||||
var beholder = state.Mobile;
|
||||
|
||||
if (beholder != m && beholder.CanSee(m))
|
||||
if (beholder == m || !beholder.CanSee(m))
|
||||
{
|
||||
if (sendRemove)
|
||||
{
|
||||
if (removeEntity[0] == 0)
|
||||
{
|
||||
OutgoingEntityPackets.CreateRemoveEntity(removeEntity, Serial);
|
||||
}
|
||||
|
||||
state.Send(removeEntity);
|
||||
}
|
||||
|
||||
if (sendIncoming)
|
||||
{
|
||||
state.Send(new MobileIncoming(state, beholder, m));
|
||||
|
||||
if (m.IsDeadBondedPet)
|
||||
{
|
||||
if (deadBuffer[0] == 0)
|
||||
{
|
||||
OutgoingMobilePackets.CreateBondedStatus(deadBuffer, m.Serial, true);
|
||||
}
|
||||
|
||||
state.Send(deadBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (sendMoving || !state.StygianAbyss && (sendHealthbarPoison || sendHealthbarYellow))
|
||||
{
|
||||
state.SendMobileMovingUsingCache(mobileMovingPackets, beholder, m);
|
||||
}
|
||||
|
||||
if (state.StygianAbyss)
|
||||
{
|
||||
if (sendHealthbarPoison)
|
||||
{
|
||||
hbpPacket ??= Packet.Acquire(new HealthbarPoison(m));
|
||||
|
||||
state.Send(hbpPacket);
|
||||
}
|
||||
|
||||
if (sendHealthbarYellow)
|
||||
{
|
||||
hbyPacket ??= Packet.Acquire(new HealthbarYellow(m));
|
||||
|
||||
state.Send(hbyPacket);
|
||||
}
|
||||
}
|
||||
|
||||
if (sendPublicStats)
|
||||
{
|
||||
if (m.CanBeRenamedBy(beholder))
|
||||
{
|
||||
statPacketTrue ??= Packet.Acquire(new MobileStatusCompact(true, m));
|
||||
|
||||
state.Send(statPacketTrue);
|
||||
}
|
||||
else
|
||||
{
|
||||
statPacketFalse ??= Packet.Acquire(new MobileStatusCompact(false, m));
|
||||
|
||||
state.Send(statPacketFalse);
|
||||
}
|
||||
}
|
||||
else if (sendHits)
|
||||
{
|
||||
hitsPacket ??= Packet.Acquire(new MobileHitsN(m));
|
||||
|
||||
state.Send(hitsPacket);
|
||||
}
|
||||
|
||||
if (sendHair)
|
||||
{
|
||||
hairPacket ??= removeHair
|
||||
? Packet.Acquire(new RemoveHair(m))
|
||||
: Packet.Acquire(new HairEquipUpdate(m));
|
||||
|
||||
state.Send(hairPacket);
|
||||
}
|
||||
|
||||
if (sendFacialHair)
|
||||
{
|
||||
facialhairPacket ??= removeFacialHair
|
||||
? Packet.Acquire(new RemoveFacialHair(m))
|
||||
: Packet.Acquire(new FacialHairEquipUpdate(m));
|
||||
|
||||
state.Send(facialhairPacket);
|
||||
}
|
||||
|
||||
SendOPLPacketTo(state);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sendRemove)
|
||||
{
|
||||
if (removeEntity[0] == 0)
|
||||
{
|
||||
OutgoingEntityPackets.CreateRemoveEntity(removeEntity, Serial);
|
||||
}
|
||||
|
||||
state.Send(removeEntity);
|
||||
}
|
||||
|
||||
if (sendIncoming)
|
||||
{
|
||||
state.Send(new MobileIncoming(state, beholder, m));
|
||||
|
||||
if (m.IsDeadBondedPet)
|
||||
{
|
||||
if (deadBuffer[0] == 0)
|
||||
{
|
||||
OutgoingMobilePackets.CreateBondedStatus(deadBuffer, m.Serial, true);
|
||||
}
|
||||
|
||||
state.Send(deadBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (sendMoving || !state.StygianAbyss && (sendHealthbarPoison || sendHealthbarYellow))
|
||||
{
|
||||
state.SendMobileMovingUsingCache(mobileMovingPackets, beholder, m);
|
||||
}
|
||||
|
||||
if (state.StygianAbyss)
|
||||
{
|
||||
if (sendHealthbarPoison)
|
||||
{
|
||||
hbpPacket ??= Packet.Acquire(new HealthbarPoison(m));
|
||||
|
||||
state.Send(hbpPacket);
|
||||
}
|
||||
|
||||
if (sendHealthbarYellow)
|
||||
{
|
||||
hbyPacket ??= Packet.Acquire(new HealthbarYellow(m));
|
||||
|
||||
state.Send(hbyPacket);
|
||||
}
|
||||
}
|
||||
|
||||
if (sendPublicStats)
|
||||
{
|
||||
if (m.CanBeRenamedBy(beholder))
|
||||
{
|
||||
statPacketTrue ??= Packet.Acquire(new MobileStatusCompact(true, m));
|
||||
|
||||
state.Send(statPacketTrue);
|
||||
}
|
||||
else
|
||||
{
|
||||
statPacketFalse ??= Packet.Acquire(new MobileStatusCompact(false, m));
|
||||
|
||||
state.Send(statPacketFalse);
|
||||
}
|
||||
}
|
||||
else if (sendHits)
|
||||
{
|
||||
if (hitsPacket[0] == 0)
|
||||
{
|
||||
OutgoingMobilePackets.CreateMobileHits(ref hitsPacket, m, true);
|
||||
}
|
||||
|
||||
state.Send(hitsPacket);
|
||||
}
|
||||
|
||||
if (sendHair)
|
||||
{
|
||||
hairPacket ??= removeHair
|
||||
? Packet.Acquire(new RemoveHair(m))
|
||||
: Packet.Acquire(new HairEquipUpdate(m));
|
||||
|
||||
state.Send(hairPacket);
|
||||
}
|
||||
|
||||
if (sendFacialHair)
|
||||
{
|
||||
facialhairPacket ??= removeFacialHair
|
||||
? Packet.Acquire(new RemoveFacialHair(m))
|
||||
: Packet.Acquire(new FacialHairEquipUpdate(m));
|
||||
|
||||
state.Send(facialhairPacket);
|
||||
}
|
||||
|
||||
SendOPLPacketTo(state);
|
||||
}
|
||||
|
||||
Packet.Release(hitsPacket);
|
||||
Packet.Release(statPacketTrue);
|
||||
Packet.Release(statPacketFalse);
|
||||
Packet.Release(hairPacket);
|
||||
|
|
@ -6652,7 +6646,6 @@ namespace Server
|
|||
if (CanRegenHits)
|
||||
{
|
||||
m_HitsTimer ??= new HitsTimer(this);
|
||||
|
||||
m_HitsTimer.Start();
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,23 +1,8 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2020 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: AttributeNormalizer.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/>. *
|
||||
*************************************************************************/
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public static class AttributeNormalizer
|
||||
{
|
||||
public static int Maximum { get; set; } = 25;
|
||||
public static int Maximum { get; set; } = 100;
|
||||
|
||||
public static bool Enabled { get; set; } = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,92 +17,6 @@ using System.Threading;
|
|||
|
||||
namespace Server.Network
|
||||
{
|
||||
public sealed class MobileHits : Packet
|
||||
{
|
||||
public MobileHits(Mobile m) : base(0xA1, 9)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
Stream.Write((short)m.HitsMax);
|
||||
Stream.Write((short)m.Hits);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileHitsN : Packet
|
||||
{
|
||||
public MobileHitsN(Mobile m) : base(0xA1, 9)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
AttributeNormalizer.Write(Stream, m.Hits, m.HitsMax);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileMana : Packet
|
||||
{
|
||||
public MobileMana(Mobile m) : base(0xA2, 9)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
Stream.Write((short)m.ManaMax);
|
||||
Stream.Write((short)m.Mana);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileManaN : Packet
|
||||
{
|
||||
public MobileManaN(Mobile m) : base(0xA2, 9)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
AttributeNormalizer.Write(Stream, m.Mana, m.ManaMax);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileStam : Packet
|
||||
{
|
||||
public MobileStam(Mobile m) : base(0xA3, 9)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
Stream.Write((short)m.StamMax);
|
||||
Stream.Write((short)m.Stam);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileStamN : Packet
|
||||
{
|
||||
public MobileStamN(Mobile m) : base(0xA3, 9)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
AttributeNormalizer.Write(Stream, m.Stam, m.StamMax);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileAttributes : Packet
|
||||
{
|
||||
public MobileAttributes(Mobile m) : base(0x2D, 17)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
|
||||
Stream.Write((short)m.HitsMax);
|
||||
Stream.Write((short)m.Hits);
|
||||
|
||||
Stream.Write((short)m.ManaMax);
|
||||
Stream.Write((short)m.Mana);
|
||||
|
||||
Stream.Write((short)m.StamMax);
|
||||
Stream.Write((short)m.Stam);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileAttributesN : Packet
|
||||
{
|
||||
public MobileAttributesN(Mobile m) : base(0x2D, 17)
|
||||
{
|
||||
Stream.Write(m.Serial);
|
||||
|
||||
AttributeNormalizer.Write(Stream, m.Hits, m.HitsMax);
|
||||
AttributeNormalizer.Write(Stream, m.Mana, m.ManaMax);
|
||||
AttributeNormalizer.Write(Stream, m.Stam, m.StamMax);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileName : Packet
|
||||
{
|
||||
public MobileName(Mobile m) : base(0x98)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ namespace Server.Network
|
|||
public const int DeathAnimationPacketLength = 13;
|
||||
public const int MobileMovingPacketLength = 17;
|
||||
public const int MobileMovingPacketCacheLength = MobileMovingPacketLength * 8 * 2; // 8 notoriety, 2 client versions
|
||||
public const int AttributeMaximum = 100;
|
||||
public const int MobileAttributePacketLength = 9;
|
||||
public const int MobileAttributesPacketLength = 17;
|
||||
|
||||
public static void CreateBondedStatus(Span<byte> buffer, Serial serial, bool bonded)
|
||||
{
|
||||
|
|
@ -135,5 +138,119 @@ namespace Server.Network
|
|||
|
||||
ns.Send(buffer);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void WriteAttribute(this ref SpanWriter writer, int max, int cur, bool normalize = false, bool reverse = false)
|
||||
{
|
||||
if (normalize && max != 0)
|
||||
{
|
||||
if (reverse)
|
||||
{
|
||||
writer.Write((short)(cur * AttributeMaximum / max));
|
||||
writer.Write((short)AttributeMaximum);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write((short)AttributeMaximum);
|
||||
writer.Write((short)(cur * AttributeMaximum / max));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reverse)
|
||||
{
|
||||
writer.Write((short)cur);
|
||||
writer.Write((short)max);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write((short)max);
|
||||
writer.Write((short)cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SendMobileHits(this NetState ns, Mobile m, bool normalize = false)
|
||||
{
|
||||
if (ns == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Span<byte> span = stackalloc byte[MobileAttributePacketLength];
|
||||
CreateMobileHits(ref span, m, normalize);
|
||||
ns.Send(span);
|
||||
}
|
||||
|
||||
public static void CreateMobileHits(ref Span<byte> buffer, Mobile m, bool normalize = false)
|
||||
{
|
||||
var writer = new SpanWriter(buffer);
|
||||
writer.Write((byte)0xA1); // Packet ID
|
||||
writer.Write(m.Serial);
|
||||
writer.WriteAttribute(m.HitsMax, m.Hits, normalize);
|
||||
}
|
||||
|
||||
public static void SendMobileMana(this NetState ns, Mobile m, bool normalize = false)
|
||||
{
|
||||
if (ns == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Span<byte> span = stackalloc byte[MobileAttributePacketLength];
|
||||
CreateMobileMana(ref span, m, normalize);
|
||||
ns.Send(span);
|
||||
}
|
||||
|
||||
public static void CreateMobileMana(ref Span<byte> buffer, Mobile m, bool normalize = false)
|
||||
{
|
||||
var writer = new SpanWriter(buffer);
|
||||
writer.Write((byte)0xA2); // Packet ID
|
||||
writer.Write(m.Serial);
|
||||
writer.WriteAttribute(m.ManaMax, m.Mana, normalize);
|
||||
}
|
||||
|
||||
public static void SendMobileStam(this NetState ns, Mobile m, bool normalize = false)
|
||||
{
|
||||
if (ns == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Span<byte> span = stackalloc byte[MobileAttributePacketLength];
|
||||
CreateMobileStam(ref span, m, normalize);
|
||||
ns.Send(span);
|
||||
}
|
||||
|
||||
public static void CreateMobileStam(ref Span<byte> buffer, Mobile m, bool normalize = false)
|
||||
{
|
||||
var writer = new SpanWriter(buffer);
|
||||
writer.Write((byte)0xA3); // Packet ID
|
||||
writer.Write(m.Serial);
|
||||
writer.WriteAttribute(m.StamMax, m.Stam, normalize);
|
||||
}
|
||||
|
||||
public static void SendMobileAttributes(this NetState ns, Mobile m, bool normalize = false)
|
||||
{
|
||||
if (ns == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Span<byte> span = stackalloc byte[MobileAttributesPacketLength];
|
||||
CreateMobileAttributes(ref span, m, normalize);
|
||||
ns.Send(span);
|
||||
}
|
||||
|
||||
public static void CreateMobileAttributes(ref Span<byte> buffer, Mobile m, bool normalize = false)
|
||||
{
|
||||
var writer = new SpanWriter(buffer);
|
||||
writer.Write((byte)0x2D); // Packet ID
|
||||
writer.Write(m.Serial);
|
||||
|
||||
writer.WriteAttribute(m.HitsMax, m.Hits, normalize);
|
||||
writer.WriteAttribute(m.ManaMax, m.Mana, normalize);
|
||||
writer.WriteAttribute(m.StamMax, m.Stam, normalize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,46 +50,36 @@ namespace Server.Engines.PartySystem
|
|||
|
||||
public void OnStamChanged(Mobile m)
|
||||
{
|
||||
Packet p = null;
|
||||
Span<byte> p = stackalloc byte[OutgoingMobilePackets.MobileAttributePacketLength];
|
||||
OutgoingMobilePackets.CreateMobileStam(ref p, m, true);
|
||||
|
||||
for (var i = 0; i < Members.Count; ++i)
|
||||
{
|
||||
var c = Members[i].Mobile;
|
||||
var ns = c.NetState;
|
||||
|
||||
if (c != m && m.Map == c.Map && Utility.InUpdateRange(c, m) && c.CanSee(m))
|
||||
if (c != m && ns != null && m.Map == c.Map && Utility.InUpdateRange(c, m) && c.CanSee(m))
|
||||
{
|
||||
if (p == null)
|
||||
{
|
||||
p = Packet.Acquire(new MobileStamN(m));
|
||||
}
|
||||
|
||||
c.Send(p);
|
||||
ns.Send(p);
|
||||
}
|
||||
}
|
||||
|
||||
Packet.Release(p);
|
||||
}
|
||||
|
||||
public void OnManaChanged(Mobile m)
|
||||
{
|
||||
Packet p = null;
|
||||
Span<byte> p = stackalloc byte[OutgoingMobilePackets.MobileAttributePacketLength];
|
||||
OutgoingMobilePackets.CreateMobileMana(ref p, m, true);
|
||||
|
||||
for (var i = 0; i < Members.Count; ++i)
|
||||
{
|
||||
var c = Members[i].Mobile;
|
||||
var ns = c.NetState;
|
||||
|
||||
if (c != m && m.Map == c.Map && Utility.InUpdateRange(c, m) && c.CanSee(m))
|
||||
if (c != m && ns != null && m.Map == c.Map && Utility.InUpdateRange(c, m) && c.CanSee(m))
|
||||
{
|
||||
if (p == null)
|
||||
{
|
||||
p = Packet.Acquire(new MobileManaN(m));
|
||||
}
|
||||
|
||||
c.Send(p);
|
||||
ns.Send(p);
|
||||
}
|
||||
}
|
||||
|
||||
Packet.Release(p);
|
||||
}
|
||||
|
||||
public void OnStatsQuery(Mobile beholder, Mobile beheld)
|
||||
|
|
@ -102,7 +92,7 @@ namespace Server.Engines.PartySystem
|
|||
beholder.Send(new MobileStatusCompact(beheld.CanBeRenamedBy(beholder), beheld));
|
||||
}
|
||||
|
||||
beholder.Send(new MobileAttributesN(beheld));
|
||||
beholder.NetState.SendMobileAttributes(beheld, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -198,11 +188,13 @@ namespace Server.Engines.PartySystem
|
|||
|
||||
if (mi == null)
|
||||
{
|
||||
var ns = m.NetState;
|
||||
Members.Add(new PartyMemberInfo(m));
|
||||
m.Party = this;
|
||||
|
||||
var memberList = Packet.Acquire(new PartyMemberList(this));
|
||||
var attrs = Packet.Acquire(new MobileAttributesN(m));
|
||||
Span<byte> attrsPacket = stackalloc byte[OutgoingMobilePackets.MobileAttributesPacketLength];
|
||||
OutgoingMobilePackets.CreateMobileAttributes(ref attrsPacket, m, true);
|
||||
|
||||
for (var i = 0; i < Members.Count; ++i)
|
||||
{
|
||||
|
|
@ -213,14 +205,13 @@ namespace Server.Engines.PartySystem
|
|||
if (f != m)
|
||||
{
|
||||
f.Send(new MobileStatusCompact(m.CanBeRenamedBy(f), m));
|
||||
f.Send(attrs);
|
||||
f.NetState?.Send(attrsPacket);
|
||||
m.Send(new MobileStatusCompact(f.CanBeRenamedBy(m), f));
|
||||
m.Send(new MobileAttributesN(f));
|
||||
ns.SendMobileAttributes(f, true);
|
||||
}
|
||||
}
|
||||
|
||||
Packet.Release(memberList);
|
||||
Packet.Release(attrs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -516,7 +507,10 @@ namespace Server.Engines.PartySystem
|
|||
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedAffixLength(m_Mobile.Name, "")];
|
||||
buffer.InitializePacket();
|
||||
|
||||
var attrs = Packet.Acquire(new MobileAttributesN(m_Mobile));
|
||||
Span<byte> attrsPacket = stackalloc byte[OutgoingMobilePackets.MobileAttributesPacketLength];
|
||||
OutgoingMobilePackets.CreateMobileAttributes(ref attrsPacket, m_Mobile, true);
|
||||
|
||||
var ns = m_Mobile.NetState;
|
||||
|
||||
foreach (var mi in p.Members)
|
||||
{
|
||||
|
|
@ -544,13 +538,11 @@ namespace Server.Engines.PartySystem
|
|||
|
||||
m.NetState?.Send(buffer);
|
||||
m.Send(new MobileStatusCompact(m_Mobile.CanBeRenamedBy(m), m_Mobile));
|
||||
m.Send(attrs);
|
||||
m.NetState?.Send(attrsPacket);
|
||||
m_Mobile.Send(new MobileStatusCompact(m.CanBeRenamedBy(m_Mobile), m));
|
||||
m_Mobile.Send(new MobileAttributesN(m));
|
||||
ns.SendMobileAttributes(m, true);
|
||||
}
|
||||
}
|
||||
|
||||
Packet.Release(attrs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,9 +61,14 @@ namespace Server.Misc
|
|||
points += 40;
|
||||
}
|
||||
|
||||
if (Core.ML && from.Race == Race.Human) // Is this affected by the cap?
|
||||
if (Core.ML && from is PlayerMobile) // does racial bonus go before/after?
|
||||
{
|
||||
points += 2;
|
||||
if (from.Race == Race.Human)
|
||||
{
|
||||
points += 2;
|
||||
}
|
||||
|
||||
points = Math.Min(points, 18);
|
||||
}
|
||||
|
||||
if (points < 0)
|
||||
|
|
@ -71,11 +76,6 @@ namespace Server.Misc
|
|||
points = 0;
|
||||
}
|
||||
|
||||
if (Core.ML && from is PlayerMobile) // does racial bonus go before/after?
|
||||
{
|
||||
points = Math.Min(points, 18);
|
||||
}
|
||||
|
||||
if (CheckTransform(from, typeof(HorrificBeastSpell)))
|
||||
{
|
||||
points += 20;
|
||||
|
|
@ -86,7 +86,7 @@ namespace Server.Misc
|
|||
points += from.Skills.Ninjitsu.Fixed / 30;
|
||||
}
|
||||
|
||||
return TimeSpan.FromSeconds(1.0 / (0.1 * (1 + points)));
|
||||
return TimeSpan.FromSeconds(10.0 / (1 + points));
|
||||
}
|
||||
|
||||
private static TimeSpan Mobile_StamRegenRate(Mobile from)
|
||||
|
|
|
|||
|
|
@ -913,7 +913,7 @@ namespace Server.Mobiles
|
|||
public virtual TimeSpan BondingDelay => TimeSpan.FromDays(7.0);
|
||||
public virtual TimeSpan BondingAbandonDelay => TimeSpan.FromDays(1.0);
|
||||
|
||||
public override bool CanRegenHits => !IsDeadPet && base.CanRegenHits;
|
||||
public override bool CanRegenHits => !IsDeadPet && !Summoned && base.CanRegenHits;
|
||||
public override bool CanRegenStam => !IsParagon && !IsDeadPet && base.CanRegenStam;
|
||||
public override bool CanRegenMana => !IsDeadPet && base.CanRegenMana;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue