//
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//
namespace MUnique.OpenMU.Tests;
using Moq;
using MUnique.OpenMU.AttributeSystem;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.GameLogic;
using MUnique.OpenMU.GameLogic.Attributes;
using MUnique.OpenMU.GameLogic.NPC;
using MUnique.OpenMU.Pathfinding;
using MonsterDefinition = MUnique.OpenMU.Persistence.BasicModel.MonsterDefinition;
using MonsterAttribute = MUnique.OpenMU.Persistence.BasicModel.MonsterAttribute;
///
/// Tests for applying changes of a to an already spawned
/// via .
///
[TestFixture]
public class MonsterAttributeReloadTests
{
private IGameContext _gameContext = null!;
///
/// Sets up a fresh game context before each test.
///
[SetUp]
public void SetUp()
{
this._gameContext = GameContextTestHelper.CreateGameContext();
}
///
/// Tests that changing a value of a takes effect on an
/// already spawned monster after is called.
///
[Test]
public async ValueTask ReloadAttributesAppliesChangedValueAsync()
{
var monster = await this.CreateMonsterAsync().ConfigureAwait(false);
var maximumHealthAttribute = monster.Definition.Attributes.First(a => a.AttributeDefinition == Stats.MaximumHealth);
Assert.That(monster.Attributes[Stats.MaximumHealth], Is.EqualTo(1000));
maximumHealthAttribute.Value = 2000;
monster.ReloadAttributes();
Assert.That(monster.Attributes[Stats.MaximumHealth], Is.EqualTo(2000));
}
///
/// Tests that adding a new takes effect on an already spawned
/// monster after is called.
///
[Test]
public async ValueTask ReloadAttributesAppliesAddedAttributeAsync()
{
var monster = await this.CreateMonsterAsync().ConfigureAwait(false);
Assert.That(monster.Attributes[Stats.AttackRatePvm], Is.EqualTo(0));
monster.Definition.Attributes.Add(new MonsterAttribute { AttributeDefinition = Stats.AttackRatePvm, Value = 50 });
monster.ReloadAttributes();
Assert.That(monster.Attributes[Stats.AttackRatePvm], Is.EqualTo(50));
}
///
/// Tests that all spawned instances of the same monster definition pick up an attribute change.
///
[Test]
public async ValueTask ReloadAttributesAppliesToAllInstancesOfDefinitionAsync()
{
var monsterDefinition = CreateMonsterDefinition();
var monster1 = await this.CreateMonsterAsync(monsterDefinition).ConfigureAwait(false);
var monster2 = await this.CreateMonsterAsync(monsterDefinition).ConfigureAwait(false);
var maximumHealthAttribute = monsterDefinition.Attributes.First(a => a.AttributeDefinition == Stats.MaximumHealth);
maximumHealthAttribute.Value = 2000;
monster1.ReloadAttributes();
monster2.ReloadAttributes();
Assert.That(monster1.Attributes[Stats.MaximumHealth], Is.EqualTo(2000));
Assert.That(monster2.Attributes[Stats.MaximumHealth], Is.EqualTo(2000));
}
private static MonsterDefinition CreateMonsterDefinition()
{
var monsterDefinition = new MonsterDefinition
{
ObjectKind = NpcObjectKind.Monster,
};
monsterDefinition.Attributes.Add(new MonsterAttribute { AttributeDefinition = Stats.MaximumHealth, Value = 1000 });
monsterDefinition.Attributes.Add(new MonsterAttribute { AttributeDefinition = Stats.DefenseBase, Value = 100 });
return monsterDefinition;
}
private ValueTask CreateMonsterAsync()
{
return this.CreateMonsterAsync(CreateMonsterDefinition());
}
private async ValueTask CreateMonsterAsync(MonsterDefinition monsterDefinition)
{
var map = await this._gameContext.GetMapAsync(0).ConfigureAwait(false);
var spawnArea = new MonsterSpawnArea
{
MonsterDefinition = monsterDefinition,
GameMap = map!.Definition,
X1 = 100,
Y1 = 100,
X2 = 100,
Y2 = 100,
Quantity = 1,
};
var monster = new Monster(
spawnArea,
monsterDefinition,
map,
NullDropGenerator.Instance,
new Mock().Object,
this._gameContext.PlugInManager,
this._gameContext.PathFinderPool);
monster.Initialize();
return monster;
}
}