PF-1: Add basic classes (#1)
All checks were successful
MANDATORY: Build project (Pflib Net) TeamCity build finished
All checks were successful
MANDATORY: Build project (Pflib Net) TeamCity build finished
Add basic classes for characters with rudimentary testing Reviewed-on: #1
This commit is contained in:
parent
80f3e6a8c7
commit
be32882cd0
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
*.user
|
||||||
47
pflib-net.Tests/characters/PlayerCharacterTest.cs
Normal file
47
pflib-net.Tests/characters/PlayerCharacterTest.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using pflib_net.characters;
|
||||||
|
using pflib_net.characters.internals.proficiencies;
|
||||||
|
using pflib_net.characters.internals.stats;
|
||||||
|
|
||||||
|
namespace pflib_net.Tests.characters;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
[TestOf(typeof(PlayerCharacter))]
|
||||||
|
public class PlayerCharacterTest
|
||||||
|
{
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void DamageReducesHp()
|
||||||
|
{
|
||||||
|
var stats = new Stats(0, 0, 0, 0, 0, 0);
|
||||||
|
var armorValues = new Dictionary<ProficiencyType, ProficiencyValue>
|
||||||
|
{
|
||||||
|
{ ProficiencyType.Unarmored, ProficiencyValue.Expert },
|
||||||
|
{ ProficiencyType.LightArmor, ProficiencyValue.None },
|
||||||
|
{ ProficiencyType.MediumArmor, ProficiencyValue.None },
|
||||||
|
{ ProficiencyType.HeavyArmor, ProficiencyValue.None }
|
||||||
|
};
|
||||||
|
var armorProficiency = new ArmorProficiency(armorValues);
|
||||||
|
var creature = new PlayerCharacter(50, stats, 5, armorProficiency);
|
||||||
|
creature.ResolveAttack(20, 20);
|
||||||
|
Assert.That(creature.GetHp(), Is.LessThan(50));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AttackFailsOnMiss()
|
||||||
|
{
|
||||||
|
var stats = new Stats(0, 0, 0, 0, 0, 0);
|
||||||
|
var armorValues = new Dictionary<ProficiencyType, ProficiencyValue>
|
||||||
|
{
|
||||||
|
{ ProficiencyType.Unarmored, ProficiencyValue.Expert },
|
||||||
|
{ ProficiencyType.LightArmor, ProficiencyValue.None },
|
||||||
|
{ ProficiencyType.MediumArmor, ProficiencyValue.None },
|
||||||
|
{ ProficiencyType.HeavyArmor, ProficiencyValue.None }
|
||||||
|
};
|
||||||
|
var armorProficiency = new ArmorProficiency(armorValues);
|
||||||
|
var creature = new PlayerCharacter(50, stats, 5, armorProficiency);
|
||||||
|
creature.ResolveAttack(0, 50);
|
||||||
|
Assert.That(creature.GetHp(), Is.EqualTo(50));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using pflib_net.characters.internals.proficiencies;
|
||||||
|
|
||||||
|
namespace pflib_net.Tests.characters.internals.proficiencies;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
[TestOf(typeof(ArmorProficiency))]
|
||||||
|
public class ArmorProficiencyTest
|
||||||
|
{
|
||||||
|
private Dictionary<ProficiencyType, int> _values = new()
|
||||||
|
{
|
||||||
|
{ ProficiencyType.Unarmored, 0},
|
||||||
|
{ ProficiencyType.LightArmor, 5 },
|
||||||
|
{ ProficiencyType.MediumArmor, 7 },
|
||||||
|
{ ProficiencyType.HeavyArmor, 9 }
|
||||||
|
};
|
||||||
|
|
||||||
|
private Dictionary<ProficiencyType, ProficiencyValue> _proficiencyValues =
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
{ ProficiencyType.Unarmored, ProficiencyValue.None },
|
||||||
|
{ ProficiencyType.LightArmor, ProficiencyValue.Trained },
|
||||||
|
{ ProficiencyType.MediumArmor, ProficiencyValue.Expert },
|
||||||
|
{ ProficiencyType.HeavyArmor, ProficiencyValue.Master }
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[TestCase(ProficiencyType.Unarmored)]
|
||||||
|
[TestCase(ProficiencyType.LightArmor)]
|
||||||
|
[TestCase(ProficiencyType.MediumArmor)]
|
||||||
|
[TestCase(ProficiencyType.HeavyArmor)]
|
||||||
|
public void GetValueReturnsCorrectAc(ProficiencyType type)
|
||||||
|
{
|
||||||
|
var armorProficiency = new ArmorProficiency(_proficiencyValues);
|
||||||
|
Assert.That(armorProficiency.GetValue(type, 3), Is.EqualTo(_values[type]));
|
||||||
|
}
|
||||||
|
}
|
||||||
40
pflib-net.Tests/characters/internals/stats/StatsTest.cs
Normal file
40
pflib-net.Tests/characters/internals/stats/StatsTest.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using pflib_net.characters.internals.stats;
|
||||||
|
|
||||||
|
namespace pflib_net.Tests.characters.internals.stats;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
[TestOf(typeof(Stats))]
|
||||||
|
public class StatsTest
|
||||||
|
{
|
||||||
|
private readonly Dictionary<StatType, int> _values = new Dictionary<StatType, int>()
|
||||||
|
{
|
||||||
|
{ StatType.Strength, 1 },
|
||||||
|
{ StatType.Dexterity, 2 },
|
||||||
|
{ StatType.Constitution, 3 },
|
||||||
|
{ StatType.Intelligence, 4 },
|
||||||
|
{ StatType.Wisdom, 5 },
|
||||||
|
{ StatType.Charisma, 6 }
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[TestCase(StatType.Strength)]
|
||||||
|
[TestCase(StatType.Dexterity)]
|
||||||
|
[TestCase(StatType.Constitution)]
|
||||||
|
[TestCase(StatType.Intelligence)]
|
||||||
|
[TestCase(StatType.Wisdom)]
|
||||||
|
[TestCase(StatType.Charisma)]
|
||||||
|
public void GetStatsGivesCorrectValues(StatType type)
|
||||||
|
{
|
||||||
|
var stats = new Stats(
|
||||||
|
_values[StatType.Strength],
|
||||||
|
_values[StatType.Dexterity],
|
||||||
|
_values[StatType.Constitution],
|
||||||
|
_values[StatType.Intelligence],
|
||||||
|
_values[StatType.Wisdom],
|
||||||
|
_values[StatType.Charisma]
|
||||||
|
);
|
||||||
|
Assert.That(stats.GetStat(type), Is.EqualTo(_values[type]));
|
||||||
|
}
|
||||||
|
}
|
||||||
20
pflib-net.Tests/pflib-net.Tests.csproj
Normal file
20
pflib-net.Tests/pflib-net.Tests.csproj
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<RootNamespace>pflib_net.Tests</RootNamespace>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
||||||
|
<PackageReference Include="NUnit" Version="4.1.0" />
|
||||||
|
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\pflib-net\pflib-net.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
22
pflib-net.sln
Normal file
22
pflib-net.sln
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pflib-net", "pflib-net\pflib-net.csproj", "{67894E72-B960-45B8-BE46-13B887EDE420}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pflib-net.Tests", "pflib-net.Tests\pflib-net.Tests.csproj", "{C27B21AF-82FC-4AED-845E-DE27602063E0}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{67894E72-B960-45B8-BE46-13B887EDE420}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{67894E72-B960-45B8-BE46-13B887EDE420}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{67894E72-B960-45B8-BE46-13B887EDE420}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{67894E72-B960-45B8-BE46-13B887EDE420}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C27B21AF-82FC-4AED-845E-DE27602063E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C27B21AF-82FC-4AED-845E-DE27602063E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C27B21AF-82FC-4AED-845E-DE27602063E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C27B21AF-82FC-4AED-845E-DE27602063E0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
17
pflib-net/characters/ICharacter.cs
Normal file
17
pflib-net/characters/ICharacter.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
namespace pflib_net.characters;
|
||||||
|
|
||||||
|
public interface ICharacter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Resolve an attack against the character's AC and deal damage appropriately
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="roll"></param>
|
||||||
|
/// <param name="damage"></param>
|
||||||
|
public void ResolveAttack(int roll, int damage);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the HP of the character
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public int GetHp();
|
||||||
|
}
|
||||||
37
pflib-net/characters/PlayerCharacter.cs
Normal file
37
pflib-net/characters/PlayerCharacter.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using pflib_net.characters.internals.proficiencies;
|
||||||
|
using pflib_net.characters.internals.stats;
|
||||||
|
|
||||||
|
namespace pflib_net.characters;
|
||||||
|
|
||||||
|
public class PlayerCharacter : ICharacter
|
||||||
|
{
|
||||||
|
private int Hp { get; set; }
|
||||||
|
private Stats Stats { get; set; }
|
||||||
|
private int Level { get; set; }
|
||||||
|
private ArmorProficiency ArmorProficiency { get; }
|
||||||
|
|
||||||
|
public PlayerCharacter(int hp, Stats stats, int level, ArmorProficiency armorProficiency)
|
||||||
|
{
|
||||||
|
Hp = hp;
|
||||||
|
Stats = stats;
|
||||||
|
Level = level;
|
||||||
|
ArmorProficiency = armorProficiency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResolveAttack(int roll, int damage)
|
||||||
|
{
|
||||||
|
if (roll < GetAc()) return;
|
||||||
|
Hp -= damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetAc()
|
||||||
|
{
|
||||||
|
return 10 + Stats.GetStat(StatType.Dexterity) + ArmorProficiency.GetValue(ProficiencyType.Unarmored, Level);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHp()
|
||||||
|
{
|
||||||
|
return Hp;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace pflib_net.characters.internals.proficiencies;
|
||||||
|
|
||||||
|
public class ArmorProficiency : IProficiency
|
||||||
|
{
|
||||||
|
private Dictionary<ProficiencyType, ProficiencyValue> Values { get; set; }
|
||||||
|
|
||||||
|
public ArmorProficiency(Dictionary<ProficiencyType, ProficiencyValue> values)
|
||||||
|
{
|
||||||
|
Values = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetValue(ProficiencyType type, int level)
|
||||||
|
{
|
||||||
|
if (Values[type].Equals(ProficiencyValue.None))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return level + (int) Values[type];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
namespace pflib_net.characters.internals.proficiencies;
|
||||||
|
|
||||||
|
public interface IProficiency
|
||||||
|
{
|
||||||
|
public int GetValue(ProficiencyType type, int level);
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
namespace pflib_net.characters.internals.proficiencies;
|
||||||
|
|
||||||
|
public enum ProficiencyType
|
||||||
|
{
|
||||||
|
Unarmored,
|
||||||
|
LightArmor,
|
||||||
|
MediumArmor,
|
||||||
|
HeavyArmor,
|
||||||
|
|
||||||
|
Unarmed,
|
||||||
|
SimpleWeapon,
|
||||||
|
MartialWeapon,
|
||||||
|
AdvancedWeapon,
|
||||||
|
|
||||||
|
SkillAcrobatics,
|
||||||
|
SkillArcana,
|
||||||
|
SkillAthletics,
|
||||||
|
SkillCrafting,
|
||||||
|
SkillDeception,
|
||||||
|
SkillDiplomacy,
|
||||||
|
SkillIntimidation,
|
||||||
|
SkillMedicine,
|
||||||
|
SkillNature,
|
||||||
|
SkillOccultism,
|
||||||
|
SkillPerformance,
|
||||||
|
SkillReligion,
|
||||||
|
SkillSociety,
|
||||||
|
SkillStealth,
|
||||||
|
SkillSurvival,
|
||||||
|
SkillThievery,
|
||||||
|
|
||||||
|
LoreBardic,
|
||||||
|
LoreLoremaster,
|
||||||
|
LoreOther
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
namespace pflib_net.characters.internals.proficiencies;
|
||||||
|
|
||||||
|
public enum ProficiencyValue: ushort
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Trained = 2,
|
||||||
|
Expert = 4,
|
||||||
|
Master = 6,
|
||||||
|
Legendary = 8
|
||||||
|
}
|
||||||
11
pflib-net/characters/internals/stats/StatType.cs
Normal file
11
pflib-net/characters/internals/stats/StatType.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace pflib_net.characters.internals.stats;
|
||||||
|
|
||||||
|
public enum StatType
|
||||||
|
{
|
||||||
|
Strength,
|
||||||
|
Dexterity,
|
||||||
|
Constitution,
|
||||||
|
Intelligence,
|
||||||
|
Wisdom,
|
||||||
|
Charisma
|
||||||
|
}
|
||||||
23
pflib-net/characters/internals/stats/Stats.cs
Normal file
23
pflib-net/characters/internals/stats/Stats.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace pflib_net.characters.internals.stats;
|
||||||
|
|
||||||
|
public class Stats
|
||||||
|
{
|
||||||
|
private Dictionary<StatType, int> StatDict { get; } = new();
|
||||||
|
|
||||||
|
public Stats(int strength, int dexterity, int constitution, int intelligence, int wisdom, int charisma)
|
||||||
|
{
|
||||||
|
StatDict[StatType.Strength] = strength;
|
||||||
|
StatDict[StatType.Dexterity] = dexterity;
|
||||||
|
StatDict[StatType.Constitution] = constitution;
|
||||||
|
StatDict[StatType.Intelligence] = intelligence;
|
||||||
|
StatDict[StatType.Wisdom] = wisdom;
|
||||||
|
StatDict[StatType.Charisma] = charisma;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetStat(StatType type)
|
||||||
|
{
|
||||||
|
return StatDict[type];
|
||||||
|
}
|
||||||
|
}
|
||||||
14
pflib-net/pflib-net.csproj
Normal file
14
pflib-net/pflib-net.csproj
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<RootNamespace>pflib_net</RootNamespace>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="conditions\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
Loading…
x
Reference in New Issue
Block a user