acdream/tests/AcDream.Plugins.MossTank.Tests/CombatItemDebuffPlannerTests.cs

182 lines
6.2 KiB
C#

using AcDream.Plugin.Abstractions;
namespace AcDream.Plugins.MossTank.Tests;
public sealed class CombatItemDebuffPlannerTests
{
[Fact]
public void SpellLevelAndSkillMethodsUseOfficialComparisonOrder()
{
PluginSpellInfo learned = Spell(1, "Imperil Other VI", 300, 31);
PluginSpellInfo lensSpell = Spell(2, "Imperil Other VII", 350, 31);
var catalog = new Catalog([learned], [learned, lensSpell]);
var character = new Character((31u, 500u));
PluginInventoryItem lens = Item(100, "Imperil Lens", 0x8000, 2) with
{
ItemSpellcraft = 100,
};
var settings = new CombatSettings
{
DebuffSelectionMethod = DebuffSelectionMethod.SpellLevel,
};
settings.CombatItemObjectIds.Add(lens.ObjectId);
MonsterRuleActions actions = Imperil();
CombatDebuffSource byLevel = Assert.Single(
CombatItemDebuffPlanner.Candidates(
actions,
settings,
character,
catalog,
[lens],
static (_, _) => true).Take(1));
Assert.Equal(CombatDebuffSourceKind.CasterItem, byLevel.Kind);
settings.DebuffSelectionMethod = DebuffSelectionMethod.Skill;
CombatDebuffSource bySkill = Assert.Single(
CombatItemDebuffPlanner.Candidates(
actions,
settings,
character,
catalog,
[lens],
static (_, _) => true).Take(1));
Assert.Equal(CombatDebuffSourceKind.LearnedSpell, bySkill.Kind);
}
[Fact]
public void ItemAndGrenadeSourcesRequireTheirExactProfiles()
{
PluginSpellInfo imperil = Spell(1323, "Imperil Other I", 100, 31);
var catalog = new Catalog([], [imperil]);
var character = new Character((38u, 400u));
PluginInventoryItem grenade = Item(
200,
"Iron Phial of Imperil",
0x100,
0) with { CombatUse = 0 };
var settings = new CombatSettings();
Assert.Empty(CombatItemDebuffPlanner.Candidates(
Imperil(), settings, character, catalog, [grenade],
static (_, _) => true));
settings.ConsumableNames.Add("Iron Phial of Imperil");
CombatDebuffSource source = Assert.Single(
CombatItemDebuffPlanner.Candidates(
Imperil(), settings, character, catalog, [grenade],
static (_, _) => true));
Assert.Equal(CombatDebuffSourceKind.Grenade, source.Kind);
Assert.Equal(200u, source.ItemObjectId);
Assert.Equal(100, source.SourceSkill);
}
[Fact]
public void ProcWeaponUsesFirstQualifyingAppraisedNonWarSpell()
{
PluginSpellInfo war = Spell(10, "Flame Bolt VII", 400, 34);
PluginSpellInfo imperil = Spell(11, "Imperil Other VII", 350, 31);
var catalog = new Catalog([], [war, imperil]);
PluginInventoryItem weapon = Item(300, "Debuff Sword", 1, 0) with
{
ItemSpellcraft = 360,
AppraisedSpellIds = [10u, 11u],
};
var settings = new CombatSettings();
settings.CombatItemObjectIds.Add(300u);
CombatDebuffSource source = Assert.Single(
CombatItemDebuffPlanner.Candidates(
Imperil(), settings, new Character(), catalog, [weapon],
static (_, _) => true));
Assert.Equal(CombatDebuffSourceKind.ProcWeapon, source.Kind);
Assert.Equal(11u, source.Spell.SpellId);
}
private static MonsterRuleActions Imperil() => new()
{
Flags = MonsterActionFlags.Imperil,
};
private static PluginSpellInfo Spell(
uint id,
string name,
int quality,
uint school) => new(
id, name, 1, 7, quality, 10, 60, school, string.Empty,
false, false)
{
IsDebuff = true,
IsOffensive = true,
TargetMask = 0x10,
};
private static PluginInventoryItem Item(
uint id,
string name,
uint itemType,
uint spellId) => new(
id, 0, name, itemType, 1, 0, 0, 0, 0, 0, 0,
1, 0, 0, spellId, 0, 0, 0, false, 0, 0, 0, 0, 0,
0, 0, 0);
private sealed class Catalog(
IReadOnlyList<PluginSpellInfo> known,
IReadOnlyList<PluginSpellInfo> all) : ISpellCatalog
{
public IReadOnlyList<PluginSpellInfo> KnownSelfBuffs => [];
public IReadOnlyList<PluginSpellInfo> KnownCombatSpells => known;
public bool TryGet(uint spellId, out PluginSpellInfo info)
{
foreach (PluginSpellInfo spell in all)
{
if (spell.SpellId == spellId)
{
info = spell;
return true;
}
}
info = default;
return false;
}
}
private sealed class Character(params (uint Id, uint Current)[] skills)
: ICharacterInfo
{
public bool IsInWorld => true;
public uint ObjectId => 1;
public uint CurrentHealth => 100;
public uint MaxHealth => 100;
public uint CurrentStamina => 100;
public uint MaxStamina => 100;
public uint CurrentMana => 100;
public uint MaxMana => 100;
public IReadOnlyList<PluginSkillInfo> Skills => skills.Select(
skill => new PluginSkillInfo(
skill.Id,
string.Empty,
PluginSkillTraining.Trained,
skill.Current)).ToArray();
public IReadOnlyList<PluginAttributeInfo> Attributes => [];
public IReadOnlyList<PluginActiveEnchantment> ActiveEnchantments => [];
public bool TryGetSkill(uint skillId, out PluginSkillInfo skill)
{
foreach ((uint id, uint current) in skills)
{
if (id == skillId)
{
skill = new PluginSkillInfo(
id,
string.Empty,
PluginSkillTraining.Trained,
current);
return true;
}
}
skill = default;
return false;
}
}
}