feat(mosstank): add VTank-style automation PoC
This commit is contained in:
parent
f6fe0f2a4f
commit
4e6e9bc9d9
212 changed files with 49462 additions and 416 deletions
|
|
@ -0,0 +1,182 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue