Updates Packets & Randomizer (#43)

* Fixes a bug with the main loop. Removes unnecessary optimizations for RDRand.

* WIP - Rewriting packets.

* Cleanup and updates README

* Converts more packets

* Fixes header

* Converts Effects packets.

* Forgot the send command

* Adds the start of containers packets.

* Adds message packets with caching

* Extends the send methods

* Starts to add Acquire methods

* Converted the packets

* Cleanup

* Cleanup

* Adds more packets

* Adds more packets

* Fixes clearing arrays from pool. Adds Mobile Incoming

* Converts more packets.

* Moves more packets

* Moves more packets

* Test compression

* Merges

* Migrating to an idiomatic syntax that also supports compression, and proxying.

* Optimize the stack alloc. Changes attributes

* Converted container packets

* Visual Studio doesn't auto save files. I am still getting used to subpar IDEs.

* Adds static packet caching. Will profile later. Converts more packets

* Fixes packets and changes how compression is configured

* WIP - Adds basics for Gumps. Not finished though.

* Fix file

* Fixes formatting

* Changed SpanWriter to be more idiomatic.

* Fixes Span vs RawSpan and missing stackallocs

* Converts over some more gumps

* WIP - Deletes 32bit support.

* Drops RDRand32 support.

* Fixes gump compilation

* Converting gump components

* Removes old huffman compression function

* Revert signature for backwards compatibility

* WIP - Converting more gump components

* Creates ArraySet for the strings. Updates AppendTo to reference that.

* Converts the maining gump components

* Cleans up gump components

* Cleans up directives

* Cleans up ArraySet and moves it. Adds null-coalescing-assignment

* Cleanup, Target Packets, and C# 8 changes.

* Removed OPL Packet

* World packets

* Fixing packet uses

* Cleans up code. Fixes packet uses in various places.

* More cleanup for packets

* Code cleanup

* Converts more packet uses and cleans up more code

* More code cleanup

* Finishes fixing the packets in Item

* Updates secure trade packets

* Updates core and gets it to compile.

* Moved packets to scripts. Fixed account handler use of packets

* Code cleanup

* Updates chat packets

* Code cleanuo

* Adds party packets, but need to implement them.

* Party packets WIP

* Finishes party packets

* Rearrange movement namespaces and classes

* Finishes plant packets

* Code Formatting

* Fixes moving effects

* Code cleanup, eliminates equipinfo

* Adds more packets. Fixes bugs with various packets.

* Finishes mahjon packets

* Fixes mahjong packet

* Code cleanup

* Finishes mahjong packets

* Adds Map packets

* Add multifacet maps and charts

* Cleans up some packets with UTF8

* Optimizes packets

* Cleans up more packets. Moves the MessageHelper

* Removes assistant support. Removes extended protocol. Incorporates MapUO packets as normal packets.

* Updates protocol extensions packet receiver

* Fixes a few bugs. Fixes a few more packets.

* Code cleanup and fixing more packets

* Fixes packet effects

* Cleaned up more code

* Buff Icon cleanup

* Removed unused constructors

* Code Cleanup. Adds BoatHS Packets

* Moves house files. Updates house foundation packets.

* Deployment cleanup

* Fixes:

* Code cleanup

* More code cleanup

* More code cleanup

* Cleaned up BaseHouse

* Enforces styling

* Converts foreach to linq where possible.

* Dont need that

* Goals/Readme updates

* Removes 32bit support at the highest level. Turns on HRT by default.

* Code cleanup. Fixes extended features packet.

* Fixes various bugs

* Code cleanup

* Code cleanup

* Code cleanup. Fixes gump X/Y assignment.

* Code cleanup using |= operator

* More code cleanup

* Cleanup

* Fixes spacing issues. Thanks Visual Studio. You suck.

* Compiler error

* Fixes NPE from RunUO 2.7

* Renames ScriptCompiler to AssemblyHandler. Fixes packets. Updates README

* Fixes more packets. Stupid trailing nulls.

* Fixes various bugs.

* Fixes for gumps

* Fixes more gump stuff. Going to split it out later since it is getting insane

* Recoded the gump writing

* WIP

* *Added output path of scripts project to dev branch
*Activated debugging in code
This commit is contained in:
Kamron Batman 2019-11-11 03:40:16 -08:00 committed by 3HMonkey
parent 7aa8fd3df1
commit 179cb50557
588 changed files with 10843 additions and 16177 deletions

View file

@ -18,7 +18,6 @@ using Server.Guilds;
using Server.Gumps;
using Server.Items;
using Server.Misc;
using Server.Movement;
using Server.Multis;
using Server.Network;
using Server.Regions;
@ -204,16 +203,7 @@ namespace Server.Mobiles
SkillName.TasteID
};
public override double RacialSkillBonus
{
get
{
if (Core.ML && Race == Race.Human)
return 20.0;
return 0;
}
}
public override double RacialSkillBonus => Core.ML && Race == Race.Human ? 20.0 : 0;
public List<Item> EquipSnapshot{ get; private set; }
@ -302,15 +292,7 @@ namespace Server.Mobiles
public DateTime SessionStart{ get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public TimeSpan GameTime
{
get
{
if (NetState != null)
return m_GameTime + (DateTime.UtcNow - SessionStart);
return m_GameTime;
}
}
public TimeSpan GameTime => NetState != null ? m_GameTime + (DateTime.UtcNow - SessionStart) : m_GameTime;
public override bool NewGuildDisplay => Guilds.Guild.NewGuildSystem;
@ -365,13 +347,9 @@ namespace Server.Mobiles
BlockMountType type = MountBlockReason;
if (!Alive)
{
SendLocalizedMessage(1113082); // You may not fly while dead.
}
else if (IsBodyMod && !(BodyMod == 666 || BodyMod == 667))
{
SendLocalizedMessage(1112453); // You can't fly in your current form!
}
else if (type != BlockMountType.None)
{
switch (type)
@ -548,10 +526,9 @@ namespace Server.Mobiles
private static void CheckPets()
{
foreach (Mobile m in World.Mobiles.Values)
if (m is PlayerMobile pm)
if ((!pm.Mounted || pm.Mount is EtherealMount) && pm.AllFollowers.Count > pm.AutoStabled.Count ||
pm.Mounted && pm.AllFollowers.Count > pm.AutoStabled.Count + 1)
pm.AutoStablePets(); /* autostable checks summons, et al: no need here */
if (m is PlayerMobile pm && ((!pm.Mounted || pm.Mount is EtherealMount) && pm.AllFollowers.Count > pm.AutoStabled.Count ||
pm.Mounted && pm.AllFollowers.Count > pm.AutoStabled.Count + 1))
pm.AutoStablePets(); /* autostable checks summons, et al: no need here */
}
private static bool CheckBlock(MountBlock block) => block?.m_Timer.Running == true;
@ -632,8 +609,8 @@ namespace Server.Mobiles
m_LastGlobalLight = global;
m_LastPersonalLight = personal;
ns.Send(GlobalLightLevel.Instantiate(global));
ns.Send(new PersonalLightLevel(this, personal));
Packets.SendGlobalLightLevel(ns, (sbyte)global);
Packets.SendPersonalLightLevel(ns, Serial, (sbyte)personal);
}
public override int GetMinResistance(ResistanceType type)
@ -677,23 +654,17 @@ namespace Server.Mobiles
if (!(from.Account is Account acct) || !acct.HasAccess(from.NetState))
{
if (from.AccessLevel == AccessLevel.Player)
notice = "The server is currently under lockdown. No players are allowed to log in at this time.";
else
notice =
"The server is currently under lockdown. You do not have sufficient access level to connect.";
notice = from.AccessLevel == AccessLevel.Player ?
"The server is currently under lockdown. No players are allowed to log in at this time." :
"The server is currently under lockdown. You do not have sufficient access level to connect.";
Timer.DelayCall(TimeSpan.FromSeconds(1.0), () => from.NetState?.Dispose());
Timer.DelayCall(TimeSpan.FromSeconds(1.0), ns => ns?.Dispose(), from.NetState);
}
else if (from.AccessLevel >= AccessLevel.Administrator)
{
notice =
"The server is currently under lockdown. As you are an administrator, you may change this from the [Admin gump.";
}
else
{
notice = "The server is currently under lockdown. You have sufficient access level to connect.";
}
from.SendGump(new NoticeGump(1060637, 30720, notice, 0xFFC000, 300, 140));
return;
@ -1050,13 +1021,9 @@ namespace Server.Mobiles
return base.CanBeHarmful(target, message, ignoreOurBlessedness);
}
public override bool CanBeBeneficial(Mobile target, bool message, bool allowDead)
{
if (DesignContext != null || target is PlayerMobile mobile && mobile.DesignContext != null)
return false;
return base.CanBeBeneficial(target, message, allowDead);
}
public override bool CanBeBeneficial(Mobile target, bool message, bool allowDead) =>
DesignContext == null && (!(target is PlayerMobile mobile) || mobile.DesignContext == null) &&
base.CanBeBeneficial(target, message, allowDead);
public override bool CheckContextMenuDisplay(IEntity target) => DesignContext == null;
@ -1116,12 +1083,10 @@ namespace Server.Mobiles
int speed = ComputeMovementSpeed(d);
bool res;
if (!Alive)
MovementImpl.IgnoreMovableImpassables = true;
res = base.Move(d);
bool res = base.Move(d);
MovementImpl.IgnoreMovableImpassables = false;
@ -1145,7 +1110,7 @@ namespace Server.Mobiles
newZ = foundation.Z + HouseFoundation.GetLevelZ(context.Level, context.Foundation);
int newX = X, newY = Y;
Movement.Movement.Offset(d, ref newX, ref newY);
Movement.Offset(d, ref newX, ref newY);
int startX = foundation.X + foundation.Components.Min.X + 1;
int startY = foundation.Y + foundation.Components.Min.Y + 1;
@ -1882,7 +1847,7 @@ namespace Server.Mobiles
pointsToGain += (int)Math.Sqrt(GameTime.TotalSeconds * 4);
pointsToGain *= 5;
pointsToGain += (int)Math.Pow(Skills.Total / 250, 2);
pointsToGain += (int)Math.Pow(Skills.Total / 250.0, 2);
if (VirtueHelper.Award(m, VirtueName.Justice, pointsToGain, ref gainedPath))
{
@ -1894,7 +1859,7 @@ namespace Server.Mobiles
m.FixedParticles(0x375A, 9, 20, 5027, EffectLayer.Waist);
m.PlaySound(0x1F7);
m_NextJustAward = DateTime.UtcNow + TimeSpan.FromMinutes(pointsToGain / 3);
m_NextJustAward = DateTime.UtcNow + TimeSpan.FromMinutes(pointsToGain / 3.0);
}
}
}
@ -1931,16 +1896,8 @@ namespace Server.Mobiles
#endregion
if (m_BuffTable != null)
{
List<BuffInfo> list = new List<BuffInfo>();
foreach (BuffInfo buff in m_BuffTable.Values)
if (!buff.RetainThroughDeath)
list.Add(buff);
for (int i = 0; i < list.Count; i++)
RemoveBuff(list[i]);
}
foreach(var buff in m_BuffTable.Values.Where(buff => !buff.RetainThroughDeath))
RemoveBuff(buff);
}
public override bool MutateSpeech(List<Mobile> hears, ref string text, ref object context)
@ -1951,14 +1908,8 @@ namespace Server.Mobiles
if (Core.ML && Skills.SpiritSpeak.Value >= 100.0)
return false;
if (Core.AOS)
for (int i = 0; i < hears.Count; ++i)
{
Mobile m = hears[i];
if (m != this && m.Skills.SpiritSpeak.Value >= 100.0)
return false;
}
if (Core.AOS && hears.Any(m => m != this && m.Skills.SpiritSpeak.Value >= 100.0))
return false;
return base.MutateSpeech(hears, ref text, ref context);
}
@ -1968,65 +1919,48 @@ namespace Server.Mobiles
if (Guilds.Guild.NewGuildSystem && (type == MessageType.Guild || type == MessageType.Alliance))
{
if (!(Guild is Guild g))
{
SendLocalizedMessage(1063142); // You are not in a guild!
}
else if (type == MessageType.Alliance)
{
if (g.Alliance?.IsMember(g) == true)
{
//g.Alliance.AllianceTextMessage( hue, "[Alliance][{0}]: {1}", this.Name, text );
g.Alliance.AllianceChat(this, text);
SendToStaffMessage(this, "[Alliance]: {0}", text);
SendToStaffMessage(this, $"[Alliance]: {text}");
AllianceMessageHue = hue;
}
else
{
SendLocalizedMessage(1071020); // You are not in an alliance!
}
}
else //Type == MessageType.Guild
{
GuildMessageHue = hue;
g.GuildChat(this, text);
SendToStaffMessage(this, "[Guild]: {0}", text);
SendToStaffMessage(this, $"[Guild]: {text}");
}
}
else
{
base.DoSpeech(text, keywords, type, hue);
}
}
private static void SendToStaffMessage(Mobile from, string text)
{
Packet p = null;
foreach (NetState ns in from.GetClientsInRange(8))
IPooledEnumerable eable = from.GetClientsInRange(8);
foreach (NetState ns in eable)
{
Mobile mob = ns.Mobile;
if (mob?.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > from.AccessLevel)
{
if (p == null)
p = Packet.Acquire(new UnicodeMessage(from.Serial, from.Body, MessageType.Regular, from.SpeechHue, 3,
from.Language, from.Name, text));
ns.Send(p);
}
Packets.SendUnicodeMessage(ns, from.Serial, from.Body, MessageType.Regular, from.SpeechHue, 3,
from.Language, from.Name, text);
}
Packet.Release(p);
eable.Free();
}
private static void SendToStaffMessage(Mobile from, string format, params object[] args)
{
SendToStaffMessage(from, string.Format(format, args));
}
public override void Damage(int amount, Mobile from)
public override void Damage(int amount, Mobile from = null, bool informMount = true)
{
if (EvilOmenSpell.TryEndEffect(this))
amount = (int)(amount * 1.25);
@ -2049,16 +1983,15 @@ namespace Server.Mobiles
from.Damage(amount, this);
}
if (from != null && Talisman is BaseTalisman talisman)
if (talisman.Protection != null && talisman.Protection.Type != null)
{
Type type = talisman.Protection.Type;
if (from != null && Talisman is BaseTalisman talisman && talisman.Protection != null && talisman.Protection.Type != null)
{
Type type = talisman.Protection.Type;
if (type.IsInstanceOfType(from))
amount = (int)(amount * (1 - (double)talisman.Protection.Amount / 100));
}
if (type.IsInstanceOfType(from))
amount = (int)(amount * (1 - (double)talisman.Protection.Amount / 100));
}
base.Damage(amount, from);
base.Damage(amount, from, informMount);
}
public override bool IsHarmfulCriminal(Mobile target)
@ -2358,32 +2291,23 @@ namespace Server.Mobiles
}
}
if (RecentlyReported == null)
RecentlyReported = new List<Mobile>();
RecentlyReported ??= new List<Mobile>();
// Professions weren't verified on 1.0 RC0
if (!CharacterCreation.VerifyProfession(Profession))
Profession = 0;
if (PermaFlags == null)
PermaFlags = new List<Mobile>();
PermaFlags ??= new List<Mobile>();
JusticeProtectors ??= new List<Mobile>();
BOBFilter ??= new BOBFilter();
if (JusticeProtectors == null)
JusticeProtectors = new List<Mobile>();
if (BOBFilter == null)
BOBFilter = new BOBFilter();
if (m_GuildRank == null)
m_GuildRank =
RankDefinition
.Member; //Default to member if going from older version to new version (only time it should be null)
//Default to member if going from older version to new version (only time it should be null)
m_GuildRank ??= RankDefinition.Member;
if (LastOnline == DateTime.MinValue && Account != null)
LastOnline = ((Account)Account).LastLogin;
if (ChampionTitles == null)
ChampionTitles = new ChampionTitleInfo();
ChampionTitles ??= new ChampionTitleInfo();
if (AccessLevel > AccessLevel.Player)
m_IgnoreMobiles = true;
@ -2797,9 +2721,10 @@ namespace Server.Mobiles
for (int i = AutoStabled.Count - 1; i >= 0; --i)
{
BaseCreature pet = AutoStabled[i] as BaseCreature;
if (!(AutoStabled[i] is BaseCreature pet))
return;
if (pet?.Deleted == true)
if (pet.Deleted)
{
pet.IsStabled = false;
pet.StabledBy = null;
@ -2831,10 +2756,8 @@ namespace Server.Mobiles
Stabled.Remove(pet);
}
else
{
SendLocalizedMessage(1049612,
pet.Name); // ~1_NAME~ remained in the stables because you have too many followers.
}
}
AutoStabled.Clear();
@ -2902,7 +2825,7 @@ namespace Server.Mobiles
public bool NinjaWepCooldown{ get; set; }
public List<Mobile> AllFollowers => m_AllFollowers ?? (m_AllFollowers = new List<Mobile>());
public List<Mobile> AllFollowers => m_AllFollowers ??= new List<Mobile>();
public RankDefinition GuildRank
{
@ -3083,14 +3006,14 @@ namespace Server.Mobiles
if (!Core.SE || !Alive)
return;
foreach (KeyValuePair<Type, int> kvp in RecoverableAmmo)
if (kvp.Value > 0)
foreach (var (key, value) in RecoverableAmmo)
if (value > 0)
{
Item ammo = null;
try
{
ammo = Activator.CreateInstance(kvp.Key) as Item;
ammo = Activator.CreateInstance(key) as Item;
}
catch
{
@ -3100,7 +3023,7 @@ namespace Server.Mobiles
if (ammo == null)
continue;
string name = ammo.Name;
ammo.Amount = kvp.Value;
ammo.Amount = value;
if (name == null)
{
@ -3180,39 +3103,21 @@ namespace Server.Mobiles
[CommandProperty(AccessLevel.GameMaster)]
public override int Str
{
get
{
if (Core.ML && AccessLevel == AccessLevel.Player)
return Math.Min(base.Str, 150);
return base.Str;
}
get => Core.ML && AccessLevel == AccessLevel.Player ? Math.Min(base.Str, 150) : base.Str;
set => base.Str = value;
}
[CommandProperty(AccessLevel.GameMaster)]
public override int Int
{
get
{
if (Core.ML && AccessLevel == AccessLevel.Player)
return Math.Min(base.Int, 150);
return base.Int;
}
get => Core.ML && AccessLevel == AccessLevel.Player ? Math.Min(base.Int, 150) : base.Int;
set => base.Int = value;
}
[CommandProperty(AccessLevel.GameMaster)]
public override int Dex
{
get
{
if (Core.ML && AccessLevel == AccessLevel.Player)
return Math.Min(base.Dex, 150);
return base.Dex;
}
get => Core.ML && AccessLevel == AccessLevel.Player ? Math.Min(base.Dex, 150) : base.Dex;
set => base.Dex = value;
}
@ -3231,36 +3136,16 @@ namespace Server.Mobiles
SendLocalizedMessage(1060868); // Target the item you wish to toggle insurance status on <ESC> to cancel
}
private bool CanInsure(Item item)
{
if (item is Container && !(item is BaseQuiver) || item is BagOfSending || item is KeyRing || item is PotionKeg ||
item is Sigil)
return false;
if (item.Stackable)
return false;
if (item.LootType == LootType.Cursed)
return false;
if (item.ItemID == 0x204E) // death shroud
return false;
if (item.Layer == Layer.Mount)
return false;
if (item.LootType == LootType.Blessed || item.LootType == LootType.Newbied || item.BlessedFor == this)
return false;
return true;
}
private bool CanInsure(Item item) =>
(!(item is Container) || item is BaseQuiver) && !(item is BagOfSending) && !(item is KeyRing) &&
!(item is PotionKeg) && !(item is Sigil) && !item.Stackable && item.LootType != LootType.Cursed &&
item.ItemID != 0x204E && item.Layer != Layer.Mount && item.LootType != LootType.Blessed &&
item.LootType != LootType.Newbied && item.BlessedFor != this;
private void ToggleItemInsurance_Callback(Mobile from, object obj)
{
if (!CheckAlive())
return;
ToggleItemInsurance_Callback(from, obj as Item, true);
if (CheckAlive())
ToggleItemInsurance_Callback(from, obj as Item, true);
}
private void ToggleItemInsurance_Callback(Mobile from, Item item, bool target)
@ -3390,9 +3275,7 @@ namespace Server.Mobiles
m_Player.AutoRenewInsurance = false;
}
else
{
m_Player.SendLocalizedMessage(1042021); // Cancelled.
}
if (m_InsuranceGump != null)
m_Player.SendGump(m_InsuranceGump.NewInstance());
@ -3404,11 +3287,7 @@ namespace Server.Mobiles
if (!CheckAlive())
return;
List<Item> items = new List<Item>();
foreach (Item item in Items)
if (DisplayInItemInsuranceGump(item))
items.Add(item);
List<Item> items = Items.Where(DisplayInItemInsuranceGump).ToList();
Container pack = Backpack;
@ -3479,11 +3358,7 @@ namespace Server.Mobiles
AddHtmlLocalized(400, 54, 70, 20, 1114311, 0x7FFF); // Insured
int balance = Banker.GetBalance(from);
int cost = 0;
for (int i = 0; i < items.Length; ++i)
if (insure[i])
cost += GetInsuranceCost(items[i]);
int cost = items.Where((t, i) => insure[i]).Sum(GetInsuranceCost);
AddHtmlLocalized(15, 420, 300, 20, 1114310, 0x7FFF); // GOLD AVAILABLE:
AddLabel(215, 420, 0x481, balance.ToString());
@ -3702,20 +3577,12 @@ namespace Server.Mobiles
private DateTime[] m_StuckMenuUses;
public bool CanUseStuckMenu()
{
if (m_StuckMenuUses == null) return true;
for (int i = 0; i < m_StuckMenuUses.Length; ++i)
if (DateTime.UtcNow - m_StuckMenuUses[i] > TimeSpan.FromDays(1.0))
return true;
return false;
}
public bool CanUseStuckMenu() =>
m_StuckMenuUses?.Any(t => DateTime.UtcNow - t > TimeSpan.FromDays(1.0)) != false;
public void UsedStuckMenu()
{
if (m_StuckMenuUses == null) m_StuckMenuUses = new DateTime[2];
m_StuckMenuUses ??= new DateTime[2];
for (int i = 0; i < m_StuckMenuUses.Length; ++i)
if (DateTime.UtcNow - m_StuckMenuUses[i] > TimeSpan.FromDays(1.0))
@ -3779,10 +3646,7 @@ namespace Server.Mobiles
m_DuelPlayer = value;
if (m_DuelPlayer == null)
DuelContext = null;
else
DuelContext = m_DuelPlayer.Participant.Context;
DuelContext = m_DuelPlayer?.Participant.Context;
bool isInTourney = DuelContext?.Finished == false && DuelContext.m_Tournament != null;
@ -3945,22 +3809,14 @@ namespace Server.Mobiles
private void DeltaEnemies(Type oldType, Type newType)
{
NetState ns = NetState;
foreach (Mobile m in GetMobilesInRange(18))
{
Type t = m.GetType();
if (t == oldType || t == newType)
{
NetState ns = NetState;
if (ns != null)
{
if (ns.StygianAbyss)
ns.Send(new MobileMoving(m, Notoriety.Compute(this, m)));
else
ns.Send(new MobileMovingOld(m, Notoriety.Compute(this, m)));
}
}
Packets.SendMobileMoving(NetState, m, Notoriety.Compute(this, m));
}
}
@ -4120,13 +3976,8 @@ namespace Server.Mobiles
return base.ApplyNameSuffix(suffix);
}
public override TimeSpan GetLogoutDelay()
{
if (Young || BedrollLogout || TestCenter.Enabled)
return TimeSpan.Zero;
return base.GetLogoutDelay();
}
public override TimeSpan GetLogoutDelay() =>
Young || BedrollLogout || TestCenter.Enabled ? TimeSpan.Zero : base.GetLogoutDelay();
private DateTime m_LastYoungMessage = DateTime.MinValue;
@ -4167,7 +4018,7 @@ namespace Server.Mobiles
return false;
}
private static Point3D[] m_TrammelDeathDestinations =
private static readonly Point3D[] m_TrammelDeathDestinations =
{
new Point3D(1481, 1612, 20),
new Point3D(2708, 2153, 0),
@ -4186,7 +4037,7 @@ namespace Server.Mobiles
new Point3D(3665, 2587, 0)
};
private static Point3D[] m_IlshenarDeathDestinations =
private static readonly Point3D[] m_IlshenarDeathDestinations =
{
new Point3D(1216, 468, -13),
new Point3D(723, 1367, -60),
@ -4199,13 +4050,13 @@ namespace Server.Mobiles
new Point3D(1722, 219, 96)
};
private static Point3D[] m_MalasDeathDestinations =
private static readonly Point3D[] m_MalasDeathDestinations =
{
new Point3D(2079, 1376, -70),
new Point3D(944, 519, -71)
};
private static Point3D[] m_TokunoDeathDestinations =
private static readonly Point3D[] m_TokunoDeathDestinations =
{
new Point3D(1166, 801, 27),
new Point3D(782, 1228, 25),
@ -4285,9 +4136,7 @@ namespace Server.Mobiles
{
if (SpeechLog.Enabled && NetState != null)
{
if (SpeechLog == null)
SpeechLog = new SpeechLog();
SpeechLog ??= new SpeechLog();
SpeechLog.Add(e.Mobile, e.Speech);
}
}
@ -4435,8 +4284,7 @@ namespace Server.Mobiles
if (m_Values == null || index < 0 || index >= m_Values.Length)
return 0;
if (m_Values[index] == null)
m_Values[index] = new TitleInfo();
m_Values[index] ??= new TitleInfo();
return m_Values[index].Value;
}
@ -4446,16 +4294,14 @@ namespace Server.Mobiles
if (m_Values == null || index < 0 || index >= m_Values.Length)
return DateTime.MinValue;
if (m_Values[index] == null)
m_Values[index] = new TitleInfo();
m_Values[index] ??= new TitleInfo();
return m_Values[index].LastDecay;
}
public void SetValue(int index, int value)
{
if (m_Values == null)
m_Values = new TitleInfo[ChampionSpawnInfo.Table.Length];
m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length];
if (value < 0)
value = 0;
@ -4463,36 +4309,31 @@ namespace Server.Mobiles
if (index < 0 || index >= m_Values.Length)
return;
if (m_Values[index] == null)
m_Values[index] = new TitleInfo();
m_Values[index] ??= new TitleInfo();
m_Values[index].Value = value;
}
public void Award(int index, int value)
{
if (m_Values == null)
m_Values = new TitleInfo[ChampionSpawnInfo.Table.Length];
m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length];
if (index < 0 || index >= m_Values.Length || value <= 0)
return;
if (m_Values[index] == null)
m_Values[index] = new TitleInfo();
m_Values[index] ??= new TitleInfo();
m_Values[index].Value += value;
}
public void Atrophy(int index, int value)
{
if (m_Values == null)
m_Values = new TitleInfo[ChampionSpawnInfo.Table.Length];
m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length];
if (index < 0 || index >= m_Values.Length || value <= 0)
return;
if (m_Values[index] == null)
m_Values[index] = new TitleInfo();
m_Values[index] ??= new TitleInfo();
int before = m_Values[index].Value;
@ -4518,9 +4359,7 @@ namespace Server.Mobiles
for (int i = 0; i < length; i++)
{
if (titles.m_Values[i] == null)
titles.m_Values[i] = new TitleInfo();
titles.m_Values[i] ??= new TitleInfo();
TitleInfo.Serialize(writer, titles.m_Values[i]);
}
}
@ -4531,8 +4370,7 @@ namespace Server.Mobiles
if (t == null)
return;
if (t.m_Values == null)
t.m_Values = new TitleInfo[ChampionSpawnInfo.Table.Length];
t.m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length];
for (int i = 0; i < t.m_Values.Length; i++)
if (t.GetLastDecay(i) + LossDelay < DateTime.UtcNow)
@ -4546,16 +4384,8 @@ namespace Server.Mobiles
if (t == null)
return;
if (t.m_Values == null)
t.m_Values = new TitleInfo[ChampionSpawnInfo.Table.Length];
int count = 1;
for (int i = 0; i < t.m_Values.Length; i++)
if (t.m_Values[i].Value > 900)
count++;
t.Harrower = Math.Max(count, t.Harrower); //Harrower titles never decay.
t.m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length];
t.Harrower = Math.Max(1 + t.m_Values.Count(t1 => t1.Value > 900), t.Harrower); //Harrower titles never decay.
}
private class TitleInfo
@ -4611,9 +4441,7 @@ namespace Server.Mobiles
public virtual void AcquireRecipe(int recipeID)
{
if (m_AcquiredRecipes == null)
m_AcquiredRecipes = new Dictionary<int, bool>();
m_AcquiredRecipes ??= new Dictionary<int, bool>();
m_AcquiredRecipes[recipeID] = true;
}
@ -4631,12 +4459,11 @@ namespace Server.Mobiles
public void ResendBuffs()
{
if (!BuffInfo.Enabled || m_BuffTable == null)
if (!BuffInfo.Enabled || m_BuffTable == null || NetState?.BuffIcon != true)
return;
if (NetState?.BuffIcon == true)
foreach (BuffInfo info in m_BuffTable.Values)
NetState.Send(new AddBuffPacket(this, info));
foreach (BuffInfo info in m_BuffTable.Values)
BuffPackets.SendAddBuff(this, info);
}
private Dictionary<BuffIcon, BuffInfo> m_BuffTable;
@ -4654,7 +4481,7 @@ namespace Server.Mobiles
m_BuffTable.Add(b.ID, b);
if (NetState?.BuffIcon == true)
NetState.Send(new AddBuffPacket(this, b));
BuffPackets.SendAddBuff(this, b);
}
public void RemoveBuff(BuffInfo b)
@ -4678,7 +4505,7 @@ namespace Server.Mobiles
m_BuffTable.Remove(b);
if (NetState?.BuffIcon == true)
NetState.Send(new RemoveBuffPacket(this, b));
BuffPackets.SendRemoveBuffPacket(NetState, Serial, (int)b);
if (m_BuffTable.Count <= 0)
m_BuffTable = null;