## Summary A meer mage fights `FightMode.Evil` and its enraged creatures carry -1000 karma, so `BaseCreature.IsEnemy` made each an enemy of the other: - The meer acquired its own enraged creatures as ordinary targets. - An enraged creature fell back to attacking its meer when nothing else was in range. It isn't `Summoned`, so it reached the meer through `AcquireNewFocusMob`'s summon-master fallback. `BaseEnraged` and `MeerMage` now override `IsEnemy` to exclude each other. Another meer's creatures stay enemies. `BaseEnraged` also pulled its meer into fights against any creature with a `SummonMaster`, which included another meer's enraged creatures. It now checks `GetMaster()`, matching the "controlled/summoned" OSI note in that method. ## Test plan - [x] `MeerAndItsEnragedCreature_AreNotEnemies`: fails before the fix - [x] `AnotherMeersEnragedCreature_StaysAnEnemy` - [x] `MeerAndItsEnragedCreature_NeverAcquireEachOther`: fails before the fix (the meer acquired its own creature) - [x] UOContent.Tests (1171 passed, 2 skipped) and Server.Tests (907) green
77 lines
2.1 KiB
C#
77 lines
2.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Server;
|
|
using Server.Mobiles;
|
|
using Xunit;
|
|
|
|
namespace UOContent.Tests.Mobiles.AI;
|
|
|
|
// A meer mage fights FightMode.Evil and its enraged creatures carry -1000 karma, so the karma rules alone
|
|
// make each an enemy of the other.
|
|
[Collection("Sequential UOContent Tests")]
|
|
public class MeerEnragedTests : IDisposable
|
|
{
|
|
private readonly List<Mobile> _created = [];
|
|
|
|
public void Dispose()
|
|
{
|
|
for (var i = 0; i < _created.Count; i++)
|
|
{
|
|
_created[i].Delete();
|
|
}
|
|
}
|
|
|
|
private T Track<T>(T m) where T : Mobile
|
|
{
|
|
_created.Add(m);
|
|
return m;
|
|
}
|
|
|
|
private static void Place(BaseCreature bc, int x)
|
|
{
|
|
var map = Map.Felucca;
|
|
bc.MoveToWorld(new Point3D(x, 1600, map.GetAverageZ(x, 1600)), map); // flat, clear line of sight both ways
|
|
bc.AIObject.AITimer.Stop();
|
|
}
|
|
|
|
private static bool Acquire(BaseCreature creature)
|
|
{
|
|
creature.NextReacquireTime = Core.TickCount - 1;
|
|
return creature.AIObject.AcquireFocusMob(creature.RangePerception, creature.FightMode, false, false, true);
|
|
}
|
|
|
|
[Fact]
|
|
public void MeerAndItsEnragedCreature_AreNotEnemies()
|
|
{
|
|
var meer = Track(new MeerMage());
|
|
var enraged = Track(new EnragedRabbit(meer));
|
|
|
|
Assert.False(enraged.IsEnemy(meer));
|
|
Assert.False(meer.IsEnemy(enraged));
|
|
}
|
|
|
|
[Fact]
|
|
public void AnotherMeersEnragedCreature_StaysAnEnemy()
|
|
{
|
|
var meer = Track(new MeerMage());
|
|
var other = Track(new MeerMage());
|
|
var enraged = Track(new EnragedRabbit(other));
|
|
|
|
Assert.True(enraged.IsEnemy(meer));
|
|
Assert.True(meer.IsEnemy(enraged));
|
|
}
|
|
|
|
[SkippableFact]
|
|
public void MeerAndItsEnragedCreature_NeverAcquireEachOther()
|
|
{
|
|
Skip.If(!Server.Tests.TestServerInitializer.TileDataLoaded, "Requires UO client map data.");
|
|
|
|
var meer = Track(new MeerMage());
|
|
var enraged = Track(new EnragedBlackBear(meer));
|
|
Place(meer, 1600);
|
|
Place(enraged, 1601);
|
|
|
|
Assert.False(Acquire(enraged));
|
|
Assert.False(Acquire(meer));
|
|
}
|
|
}
|