fix: BaseCreature cleanup (#858)

* Removes LINQ
* Removes some list allocations
This commit is contained in:
Kamron Batman 2021-11-21 09:43:09 -08:00 committed by GitHub
parent 43db0d09c9
commit 1bec4feb0d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Collections;
using Server.ContextMenus;
using Server.Engines.ConPVP;
using Server.Engines.MLQuests;
@ -512,11 +512,11 @@ namespace Server.Mobiles
public virtual bool DeathAdderCharmable => false;
// TODO: Find the pub 31 tweaks to the DispelDifficulty and apply them of course.
public virtual double DispelDifficulty // at this skill level we dispel 50% chance
=> 0.0;
// at this skill level we dispel 50% chance
public virtual double DispelDifficulty => 0.0;
public virtual double DispelFocus // at difficulty - focus we have 0%, at difficulty + focus we have 100%
=> 20.0;
// at difficulty - focus we have 0%, at difficulty + focus we have 100%
public virtual double DispelFocus => 20.0;
public virtual bool DisplayWeight => Backpack is StrongBackpack;
@ -1169,9 +1169,8 @@ namespace Server.Mobiles
if (m_MLQuests == null)
{
return
MLQuestSystem
.EmptyList; // return EmptyList, but don't cache it (run construction again next time)
// return EmptyList, but don't cache it (run construction again next time)
return MLQuestSystem.EmptyList;
}
}
@ -1211,7 +1210,7 @@ namespace Server.Mobiles
return false;
}
if (!(m is BaseCreature c) || m is MilitiaFighter)
if (m is not BaseCreature c || m is MilitiaFighter)
{
return true;
}
@ -2153,11 +2152,8 @@ namespace Server.Mobiles
// even if they can't offer you anything at the moment
if (MLQuestSystem.Enabled && CanGiveMLQuest && from is PlayerMobile mobile)
{
MLQuestSystem.Tell(
this,
mobile,
1074893
); // You need to mark your quest items so I don't take the wrong object. Then speak to me.
// You need to mark your quest items so I don't take the wrong object. Then speak to me.
MLQuestSystem.Tell(this, mobile, 1074893);
return false;
}
@ -2536,8 +2532,8 @@ namespace Server.Mobiles
public override bool IsHarmfulCriminal(Mobile target) =>
(!Controlled || target != m_ControlMaster) && (!Summoned || target != m_SummonMaster) &&
(!(target is BaseCreature creature) || !creature.InitialInnocent || creature.Controlled) &&
(!(target is PlayerMobile mobile) || mobile.PermaFlags.Count <= 0) && base.IsHarmfulCriminal(target);
(target is not BaseCreature { InitialInnocent: true } creature || creature.Controlled) &&
(target is not PlayerMobile mobile || mobile.PermaFlags.Count <= 0) && base.IsHarmfulCriminal(target);
public override void CriminalAction(bool message)
{
@ -2837,18 +2833,6 @@ namespace Server.Mobiles
return null;
}
public static void Cap(ref int val, int min, int max)
{
if (val < min)
{
val = min;
}
else if (val > max)
{
val = max;
}
}
public override void OnDoubleClick(Mobile from)
{
if (from.AccessLevel >= AccessLevel.GameMaster && !Body.IsHuman)
@ -2903,7 +2887,8 @@ namespace Server.Mobiles
}
else if (Controlled && Commandable)
{
if (IsBonded) // Intentional difference (showing ONLY bonded when bonded instead of bonded & tame)
// Intentional difference (showing ONLY bonded when bonded instead of bonded & tame)
if (IsBonded)
{
list.Add(1049608); // (bonded)
}
@ -3028,7 +3013,7 @@ namespace Server.Mobiles
{
var de = list[i];
if (de.Damager == m || !(de.Damager is BaseCreature bc))
if (de.Damager == m || de.Damager is not BaseCreature bc)
{
continue;
}
@ -3144,10 +3129,8 @@ namespace Server.Mobiles
if (rights.Count > 0)
{
rights[0].m_Damage =
(int)(rights[0].m_Damage *
1.25
); // This would be the first valid person attacking it. Gets a 25% bonus. Per 1/19/07 Five on Friday
// This would be the first valid person attacking it. Gets a 25% bonus. Per 1/19/07 Five on Friday
rights[0].m_Damage = (int)(rights[0].m_Damage * 1.25);
if (rights.Count > 1)
{
@ -3155,24 +3138,14 @@ namespace Server.Mobiles
}
var topDamage = rights[0].m_Damage;
int minDamage;
if (hitsMax >= 3000)
int minDamage = hitsMax switch
{
minDamage = topDamage / 16;
}
else if (hitsMax >= 1000)
{
minDamage = topDamage / 8;
}
else if (hitsMax >= 200)
{
minDamage = topDamage / 4;
}
else
{
minDamage = topDamage / 2;
}
>= 3000 => topDamage / 16,
>= 1000 => topDamage / 8,
>= 200 => topDamage / 4,
_ => topDamage / 2
};
for (var i = 0; i < rights.Count; ++i)
{
@ -3271,127 +3244,126 @@ namespace Server.Mobiles
GiftOfLifeSpell.HandleDeath(this);
CheckStatTimers();
return;
}
else
{
if (!Summoned && !NoKillAwards)
{
var totalFame = Fame / 100;
var totalKarma = -Karma / 100;
if (Map == Map.Felucca)
if (!Summoned && !NoKillAwards)
{
var totalFame = Fame / 100;
var totalKarma = -Karma / 100;
if (Map == Map.Felucca)
{
totalFame += totalFame / 10 * 3;
totalKarma += totalKarma / 10 * 3;
}
var list = GetLootingRights(DamageEntries, HitsMax);
var titles = new List<Mobile>();
var fame = new List<int>();
var karma = new List<int>();
var givenQuestKill = false;
var givenFactionKill = false;
var givenToTKill = false;
for (var i = 0; i < list.Count; ++i)
{
var ds = list[i];
if (!ds.m_HasRight)
{
totalFame += totalFame / 10 * 3;
totalKarma += totalKarma / 10 * 3;
continue;
}
var list = GetLootingRights(DamageEntries, HitsMax);
var titles = new List<Mobile>();
var fame = new List<int>();
var karma = new List<int>();
var party = Engines.PartySystem.Party.Get(ds.m_Mobile);
var givenQuestKill = false;
var givenFactionKill = false;
var givenToTKill = false;
for (var i = 0; i < list.Count; ++i)
if (party != null)
{
var ds = list[i];
var divedFame = totalFame / party.Members.Count;
var divedKarma = totalKarma / party.Members.Count;
if (!ds.m_HasRight)
for (var j = 0; j < party.Members.Count; ++j)
{
var info = party.Members[j];
if (info?.Mobile != null)
{
var index = titles.IndexOf(info.Mobile);
if (index == -1)
{
titles.Add(info.Mobile);
fame.Add(divedFame);
karma.Add(divedKarma);
}
else
{
fame[index] += divedFame;
karma[index] += divedKarma;
}
}
}
}
else
{
titles.Add(ds.m_Mobile);
fame.Add(totalFame);
karma.Add(totalKarma);
}
OnKilledBy(ds.m_Mobile);
if (!givenFactionKill)
{
givenFactionKill = true;
Faction.HandleDeath(this, ds.m_Mobile);
}
var region = ds.m_Mobile.Region;
if (!givenToTKill && (Map == Map.Tokuno || region.IsPartOf("Yomotsu Mines") ||
region.IsPartOf("Fan Dancer's Dojo")))
{
givenToTKill = true;
TreasuresOfTokuno.HandleKill(this, ds.m_Mobile);
}
if (ds.m_Mobile is PlayerMobile pm)
{
if (MLQuestSystem.Enabled)
{
MLQuestSystem.HandleKill(pm, this);
}
if (givenQuestKill)
{
continue;
}
var party = Engines.PartySystem.Party.Get(ds.m_Mobile);
var qs = pm.Quest;
if (party != null)
if (qs != null)
{
var divedFame = totalFame / party.Members.Count;
var divedKarma = totalKarma / party.Members.Count;
for (var j = 0; j < party.Members.Count; ++j)
{
var info = party.Members[j];
if (info?.Mobile != null)
{
var index = titles.IndexOf(info.Mobile);
if (index == -1)
{
titles.Add(info.Mobile);
fame.Add(divedFame);
karma.Add(divedKarma);
}
else
{
fame[index] += divedFame;
karma[index] += divedKarma;
}
}
}
qs.OnKill(this, c);
givenQuestKill = true;
}
else
{
titles.Add(ds.m_Mobile);
fame.Add(totalFame);
karma.Add(totalKarma);
}
OnKilledBy(ds.m_Mobile);
if (!givenFactionKill)
{
givenFactionKill = true;
Faction.HandleDeath(this, ds.m_Mobile);
}
var region = ds.m_Mobile.Region;
if (!givenToTKill && (Map == Map.Tokuno || region.IsPartOf("Yomotsu Mines") ||
region.IsPartOf("Fan Dancer's Dojo")))
{
givenToTKill = true;
TreasuresOfTokuno.HandleKill(this, ds.m_Mobile);
}
if (ds.m_Mobile is PlayerMobile pm)
{
if (MLQuestSystem.Enabled)
{
MLQuestSystem.HandleKill(pm, this);
}
if (givenQuestKill)
{
continue;
}
var qs = pm.Quest;
if (qs != null)
{
qs.OnKill(this, c);
givenQuestKill = true;
}
}
}
for (var i = 0; i < titles.Count; ++i)
{
Titles.AwardFame(titles[i], fame[i], true);
Titles.AwardKarma(titles[i], karma[i], true);
}
}
base.OnDeath(c);
if (DeleteCorpseOnDeath)
for (var i = 0; i < titles.Count; ++i)
{
c.Delete();
Titles.AwardFame(titles[i], fame[i], true);
Titles.AwardKarma(titles[i], karma[i], true);
}
}
base.OnDeath(c);
if (DeleteCorpseOnDeath)
{
c.Delete();
}
}
public override void OnDelete()
@ -3642,17 +3614,25 @@ namespace Server.Mobiles
public virtual bool Rummage()
{
var eable = GetItemsInRange<Corpse>(2);
var toRummage = eable.FirstOrDefault(item => item.Items.Count > 0);
eable.Free();
if (toRummage == null)
if (Backpack == null)
{
return false;
}
if (Backpack == null)
var eable = GetItemsInRange<Corpse>(2);
Corpse toRummage = null;
foreach (var c in eable)
{
if (c.Items.Count > 0)
{
toRummage = c;
break;
}
}
eable.Free();
if (toRummage == null)
{
return false;
}
@ -3788,27 +3768,24 @@ namespace Server.Mobiles
public static void TeleportPets(Mobile master, Point3D loc, Map map, bool onlyBonded = false)
{
var move = new List<Mobile>();
using var queue = PooledRefQueue<Mobile>.Create();
foreach (var m in master.GetMobilesInRange(3))
var eable = master.GetMobilesInRange(3);
foreach (var m in eable)
{
if (
m is BaseCreature {
Controlled: true,
ControlOrder: OrderType.Guard or OrderType.Follow or OrderType.Come
} pet
)
if (m is BaseCreature
{ Controlled: true, ControlOrder: OrderType.Guard or OrderType.Follow or OrderType.Come } pet &&
pet.ControlMaster == master && (!onlyBonded || pet.IsBonded))
{
if (pet.ControlMaster == master && (!onlyBonded || pet.IsBonded))
{
move.Add(pet);
}
queue.Enqueue(pet);
}
}
foreach (var m in move)
eable.Free();
while (queue.Count > 0)
{
m.MoveToWorld(loc, map);
queue.Dequeue().MoveToWorld(loc, map);
}
}
@ -3844,18 +3821,14 @@ namespace Server.Mobiles
var owner = ControlMaster;
if (owner?.Deleted != false || owner.Map != Map || !owner.InRange(this, 12) || !CanSee(owner) ||
!InLOS(owner))
{
if (OwnerAbandonTime == DateTime.MinValue)
{
OwnerAbandonTime = Core.Now;
}
}
else
if (owner?.Deleted == false && owner.Map == Map && owner.InRange(this, 12) && CanSee(owner) && InLOS(owner))
{
OwnerAbandonTime = DateTime.MinValue;
}
else if (OwnerAbandonTime == DateTime.MinValue)
{
OwnerAbandonTime = Core.Now;
}
CheckStatTimers();
}
@ -3961,7 +3934,7 @@ namespace Server.Mobiles
public void BeginDeleteTimer()
{
if (!(this is BaseEscortable) && !Summoned && !Deleted && !IsStabled)
if (this is not BaseEscortable && !Summoned && !Deleted && !IsStabled)
{
StopDeleteTimer();
m_DeleteTimer = new DeleteTimer(this, TimeSpan.FromDays(3.0));
@ -4261,40 +4234,13 @@ namespace Server.Mobiles
{
}
public virtual bool CheckFoodPreference(Item f)
{
if (CheckFoodPreference(f, FoodType.Eggs, m_Eggs))
{
return true;
}
if (CheckFoodPreference(f, FoodType.Fish, m_Fish))
{
return true;
}
if (CheckFoodPreference(f, FoodType.GrainsAndHay, m_GrainsAndHay))
{
return true;
}
if (CheckFoodPreference(f, FoodType.Meat, m_Meat))
{
return true;
}
if (CheckFoodPreference(f, FoodType.FruitsAndVegies, m_FruitsAndVegies))
{
return true;
}
if (CheckFoodPreference(f, FoodType.Gold, m_Gold))
{
return true;
}
return false;
}
public virtual bool CheckFoodPreference(Item f) =>
CheckFoodPreference(f, FoodType.Eggs, m_Eggs) ||
CheckFoodPreference(f, FoodType.Fish, m_Fish) ||
CheckFoodPreference(f, FoodType.GrainsAndHay, m_GrainsAndHay) ||
CheckFoodPreference(f, FoodType.Meat, m_Meat) ||
CheckFoodPreference(f, FoodType.FruitsAndVegies, m_FruitsAndVegies) ||
CheckFoodPreference(f, FoodType.Gold, m_Gold);
public virtual bool CheckFoodPreference(Item fed, FoodType type, Type[] types)
{
@ -4396,9 +4342,8 @@ namespace Server.Mobiles
}
else if (Core.ML)
{
from.SendLocalizedMessage(
1075268
); // Your pet cannot form a bond with you until your animal taming ability has risen.
// Your pet cannot form a bond with you until your animal taming ability has risen.
from.SendLocalizedMessage(1075268);
}
}
}
@ -4454,12 +4399,7 @@ namespace Server.Mobiles
return false;
}
if (!Core.AOS && (skill == SkillName.Focus || skill == SkillName.Chivalry || skill == SkillName.Necromancy))
{
return false;
}
return true;
return Core.AOS || skill != SkillName.Focus && skill != SkillName.Chivalry && skill != SkillName.Necromancy;
}
public virtual TeachResult CheckTeachSkills(
@ -5033,8 +4973,8 @@ namespace Server.Mobiles
return false;
}
Cap(ref minLevel, 0, 5);
Cap(ref maxLevel, 0, 5);
minLevel = Math.Clamp(minLevel, 0, 5);
maxLevel = Math.Clamp(maxLevel, 0, 5);
if (Core.AOS)
{
@ -5121,9 +5061,7 @@ namespace Server.Mobiles
if (min > max)
{
var hold = min;
min = max;
max = hold;
(min, max) = (max, min);
}
/* Example:
@ -5204,8 +5142,8 @@ namespace Server.Mobiles
return false;
}
Cap(ref minLevel, 0, 5);
Cap(ref maxLevel, 0, 5);
minLevel = Math.Clamp(minLevel, 0, 5);
maxLevel = Math.Clamp(maxLevel, 0, 5);
if (Core.AOS)
{
@ -5481,15 +5419,21 @@ namespace Server.Mobiles
}
var eable = GetMobilesInRange(AuraRange);
var list = eable.Where(
m =>
m != this && CanBeHarmful(m, false) && (Core.AOS || InLOS(m)) &&
(m is BaseCreature bc && (bc.Controlled || bc.Summoned || bc.Team != Team) || m.Player)
);
foreach (var m in list)
using var queue = PooledRefQueue<Mobile>.Create();
foreach (var m in eable)
{
if (m != this && CanBeHarmful(m, false) && (Core.AOS || InLOS(m)) &&
(m is BaseCreature bc && (bc.Controlled || bc.Summoned || bc.Team != Team) || m.Player))
{
queue.Enqueue(m);
}
}
eable.Free();
while (queue.Count > 0)
{
var m = queue.Dequeue();
AOS.Damage(
m,
this,
@ -5503,8 +5447,6 @@ namespace Server.Mobiles
);
AuraEffect(m);
}
eable.Free();
}
public virtual void AuraEffect(Mobile m)
@ -5599,10 +5541,8 @@ namespace Server.Mobiles
private DateTime m_NextHourlyCheck;
public LoyaltyTimer() : base(InternalDelay, InternalDelay)
{
public LoyaltyTimer() : base(InternalDelay, InternalDelay) =>
m_NextHourlyCheck = Core.Now + TimeSpan.FromHours(1.0);
}
public static void Initialize()
{
@ -5618,14 +5558,14 @@ namespace Server.Mobiles
m_NextHourlyCheck = Core.Now + TimeSpan.FromHours(1.0);
var toRelease = new List<BaseCreature>();
using var toRelease = PooledRefQueue<BaseCreature>.Create();
// added array for wild creatures in house regions to be removed
var toRemove = new List<BaseCreature>();
using var toRemove = PooledRefQueue<Mobile>.Create();
foreach (var m in World.Mobiles.Values)
{
if (!(m is BaseCreature c))
if (m is not BaseCreature c)
{
continue;
}
@ -5649,7 +5589,7 @@ namespace Server.Mobiles
}
else if (c.OwnerAbandonTime + c.BondingAbandonDelay <= Core.Now)
{
toRemove.Add(c);
toRemove.Enqueue(c);
}
}
else
@ -5673,7 +5613,7 @@ namespace Server.Mobiles
if (c.Loyalty <= 0)
{
toRelease.Add(c);
toRelease.Enqueue(c);
}
}
}
@ -5686,7 +5626,7 @@ namespace Server.Mobiles
if (c.RemoveStep >= 20)
{
toRemove.Add(c);
toRemove.Enqueue(c);
}
}
else
@ -5695,22 +5635,24 @@ namespace Server.Mobiles
}
}
foreach (var c in toRelease)
while (toRelease.Count > 0)
{
c.Say(1043255, c.Name); // ~1_NAME~ appears to have decided that is better off without a master!
var c = toRelease.Dequeue();
c.Say(1043255, c.Name); // ~1_NAME~ appears to have decided that is better off without a master!
c.Loyalty = BaseCreature.MaxLoyalty; // Wonderfully Happy
c.IsBonded = false;
c.BondingBegin = DateTime.MinValue;
c.OwnerAbandonTime = DateTime.MinValue;
c.ControlTarget = null;
c.AIObject
.DoOrderRelease(); // this will prevent no release of creatures left alone with AI disabled (and consequent bug of Followers)
// This will prevent no release of creatures left alone with AI disabled (and consequent bug of Followers)
c.AIObject.DoOrderRelease();
c.DropBackpack();
}
foreach (var c in toRemove)
while (toRemove.Count > 0)
{
c.Delete();
toRemove.Dequeue().Delete();
}
}
}