fix: Fixes stabled, abilities targeting self, and unsummon memory leak (#1418)

## **MAJOR CHANGE**
* `Stabled` has been moved to `PlayerMobile`.
* New methods added, `PlayerMobile.AddStabled` and `PlayerMobile.RemoveStabled`.
* Added `PlayerMobile.AddFollower` and `PlayerMobile.RemoveFollower`.
* `Stabled`, `AutoStabled`, and `AllFollowers` are now `HashSet` and **_CAN BE NULL_**.

### Summary
* Fixes monster abilities causing harm to the monster through reflect
* Adds `CanTriggerAgainstSelf` to override this for healing or some other self-affecting ability
* Fixes a major memory leak where `UnsummonTimer` from animated dead spell lasts up-to 24hrs and therefore holds onto references of dead/deleted mobs.
* Fixes another minor leak where a mob is not unregistered from the animated dead spell list until the next spell cast.
This commit is contained in:
Kamron Batman 2023-07-03 09:45:22 -07:00 • committed by GitHub
parent d99e72db8f
commit 3b97e8d39c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 391 additions and 280 deletions

View file

@ -2082,23 +2082,9 @@ namespace Server.Mobiles
OwnerAbandonTime = reader.ReadDateTime();
}
if (version >= 11)
{
m_HasGeneratedLoot = reader.ReadBool();
}
else
{
m_HasGeneratedLoot = true;
}
m_HasGeneratedLoot = version < 11 || reader.ReadBool();
if (version >= 12)
{
m_Paragon = reader.ReadBool();
}
else
{
m_Paragon = false;
}
m_Paragon = version >= 12 && reader.ReadBool();
if (version >= 13 && reader.ReadBool())
{
@ -2275,30 +2261,17 @@ namespace Server.Mobiles
{
if (m_ControlMaster != null)
{
m_ControlMaster.Followers -= ControlSlots;
m_ControlMaster.Followers -= Math.Min(ControlSlots, m_ControlMaster.Followers);
if (m_ControlMaster is PlayerMobile mobile)
{
mobile.AllFollowers.Remove(this);
if (mobile.AutoStabled.Contains(this))
{
mobile.AutoStabled.Remove(this);
}
mobile.AllFollowers?.Remove(this);
mobile.AutoStabled?.Remove(this);
}
}
else if (m_SummonMaster != null)
{
m_SummonMaster.Followers -= ControlSlots;
(m_SummonMaster as PlayerMobile)?.AllFollowers.Remove(this);
}
if (m_ControlMaster?.Followers < 0)
{
m_ControlMaster.Followers = 0;
}
if (m_SummonMaster?.Followers < 0)
{
m_SummonMaster.Followers = 0;
m_SummonMaster.Followers -= Math.Min(ControlSlots, m_SummonMaster.Followers);
(m_SummonMaster as PlayerMobile)?.AllFollowers?.Remove(this);
}
}
@ -2307,17 +2280,17 @@ namespace Server.Mobiles
if (m_ControlMaster != null)
{
m_ControlMaster.Followers += ControlSlots;
if (m_ControlMaster is PlayerMobile mobile)
if (m_ControlMaster is PlayerMobile pm)
{
mobile.AllFollowers.Add(this);
pm.AddFollower(this);
}
}
else if (m_SummonMaster != null)
{
m_SummonMaster.Followers += ControlSlots;
if (m_SummonMaster is PlayerMobile mobile)
if (m_SummonMaster is PlayerMobile pm)
{
mobile.AllFollowers.Add(this);
pm.AddFollower(this);
}
}
}
@ -2407,6 +2380,8 @@ namespace Server.Mobiles
MLQuestSystem.HandleDeletion(this);
}
UnsummonTimer.StopTimer(this);
base.OnAfterDelete();
}
@ -3440,6 +3415,8 @@ namespace Server.Mobiles
}
}
RemoveFollowers();
base.OnDeath(c);
if (DeleteCorpseOnDeath)
@ -3455,6 +3432,7 @@ namespace Server.Mobiles
SummonMaster = null;
ReceivedHonorContext?.Cancel();
base.OnDelete();
m?.InvalidateProperties();
}
@ -3834,11 +3812,10 @@ namespace Server.Mobiles
public static void TeleportPets(Mobile master, Point3D loc, Map map, bool onlyBonded = false)
{
if (master is PlayerMobile pm)
if (master is PlayerMobile { AllFollowers: not null } pm)
{
for (var i = 0; i < pm.AllFollowers.Count; i++)
foreach (var m in pm.AllFollowers)
{
var m = pm.AllFollowers[i];
if (m.Map == master.Map && master.InRange(m, 3) && m is BaseCreature
{ Controlled: true, ControlOrder: OrderType.Guard or OrderType.Follow or OrderType.Come } pet &&
pet.ControlMaster == master && (!onlyBonded || pet.IsBonded))