1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-06-16 04:25:23 +00:00

Mob and Playerstate (#31)

* Filled out eLevelId enum
- Added OpenDiablo2.Core.UT unit test project
- Added ELevelIdHelper class which contains code that generates the enum from the mpq data
- Added a unit test that verifies EngineDataManager works
- Added a unit test that runs the ELevelIdHelper generate function
- Renamed some enum values for constistency (e.g. Act1_Town -> Act1_Town1, as it is in the mpq)
* Retargeted OpenDiablo2.Core.UT to .net Framework 4.6.1
* Added TestConsole
TestConsole currently only supports writing the elevelids enum to a file
Also, removed elevelids generation unit test
* PlayerState and MobState
This commit is contained in:
nicholasdechiara 2018-11-29 21:20:29 -05:00 committed by Tim Sarbin
parent f3793e0a60
commit 55f8f3ef34
41 changed files with 2338 additions and 531 deletions

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSTest.TestAdapter.1.2.0\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.1.2.0\build\net45\MSTest.TestAdapter.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{77B00705-A2A5-4675-9A16-1FAB2692151B}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OpenDiablo2.Common.UT</RootNamespace>
<AssemblyName>OpenDiablo2.Common.UT</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.2.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.2.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="UT_MobState.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UT_PlayerState.cs" />
<Compile Include="UT_Stat.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenDiablo2.Common\OpenDiablo2.Common.csproj">
<Project>{B743160E-A0BB-45DC-9998-967A85E50562}</Project>
<Name>OpenDiablo2.Common</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.2.0\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.2.0\build\net45\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.2.0\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.2.0\build\net45\MSTest.TestAdapter.targets'))" />
</Target>
<Import Project="..\packages\MSTest.TestAdapter.1.2.0\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.1.2.0\build\net45\MSTest.TestAdapter.targets')" />
</Project>

View File

@ -0,0 +1,20 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("OpenDiablo2.Common.UT")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OpenDiablo2.Common.UT")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("77b00705-a2a5-4675-9a16-1fab2692151b")]
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -0,0 +1,56 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenDiablo2.Common.Enums.Mobs;
using OpenDiablo2.Common.Models.Mobs;
namespace OpenDiablo2.Common.UT
{
[TestClass]
public class UT_MobState
{
[TestMethod]
public void MobDeathTest()
{
MobState mob = new MobState("test1", 1, 1, 100, 0, 0);
mob.TakeDamage(1000, Enums.Mobs.eDamageTypes.NONE);
Assert.AreEqual(false, mob.Alive);
}
[TestMethod]
public void MobFlagsTest()
{
MobState mob = new MobState("test1", 1, 1, 100, 0, 0);
mob.AddFlag(Enums.Mobs.eMobFlags.ENEMY);
Assert.AreEqual(true, mob.HasFlag(Enums.Mobs.eMobFlags.ENEMY));
Assert.AreEqual(false, mob.HasFlag(Enums.Mobs.eMobFlags.INVULNERABLE));
mob.RemoveFlag(Enums.Mobs.eMobFlags.ENEMY);
Assert.AreEqual(false, mob.HasFlag(Enums.Mobs.eMobFlags.ENEMY));
}
[TestMethod]
public void MobResistancesTest()
{
MobState mob = new MobState("test1", 1, 1, 100, 0, 0);
mob.SetResistance(eDamageTypes.COLD, 0.5);
int dam = mob.TakeDamage(100, eDamageTypes.COLD); // now try 100 cold damage
Assert.AreEqual(50, dam); // b/c mob has 50% resistance, should only take 50 damage
Assert.IsTrue(mob.Alive); // mob should not have taken enough damage to die
int dam2 = mob.TakeDamage(100, eDamageTypes.FIRE); // now try 100 fire damage
Assert.AreEqual(100, dam2); // b/c mob has no fire resistance, should take full damage
Assert.IsFalse(mob.Alive); // mob should be dead
}
[TestMethod]
public void MobImmunityTest()
{
MobState mob = new MobState("test1", 1, 1, 100, 0, 0);
mob.AddImmunitiy(eDamageTypes.COLD);
int dam = mob.TakeDamage(100, eDamageTypes.COLD); // now try 100 cold damage
Assert.AreEqual(0, dam); // b/c mob has immunity, should not take damage
Assert.IsTrue(mob.Alive); // mob should not have taken enough damage to die
int dam2 = mob.TakeDamage(100, eDamageTypes.FIRE); // now try 100 fire damage
Assert.AreEqual(100, dam2); // b/c mob has no fire immunity, should take full damage
Assert.IsFalse(mob.Alive); // mob should be dead
}
}
}

View File

@ -0,0 +1,72 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenDiablo2.Common.Models.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.UT
{
[TestClass]
public class UT_PlayerState
{
private PlayerState MakePlayer()
{
HeroTypeConfig herotypeconfig = new HeroTypeConfig(vitality: 20, strength: 20, dexterity: 20,
energy: 20, health: 50, mana: 40, stamina: 30,
perlevelhealth: 3, perlevelmana: 1.5, perlevelstamina: 1,
pervitalityhealth: 2, pervitalitystamina: 1, perenergymana: 1.5,
baseatkrating: -30, basedefrating: -30, perdexterityatkrating: 5, perdexteritydefrating: 4);
LevelExperienceConfig expconfig = new LevelExperienceConfig(new List<int>()
{
0, // level 0
0, // level 1
500, // level 2
1500, // level 3
2250,
4125,
});
PlayerState ps = new PlayerState("player1", id: 1, level: 1, x: 0, y: 0,
vitality: herotypeconfig.StartingVitality,
strength: herotypeconfig.StartingStrength,
energy: herotypeconfig.StartingEnergy,
dexterity: herotypeconfig.StartingDexterity,
experience: 0,
herotype: Enums.eHero.Amazon,
heroconfig: herotypeconfig,
expconfig: expconfig);
return ps;
}
[TestMethod]
public void PlayerLevelUpTest()
{
PlayerState ps = MakePlayer();
int level1hp = ps.GetHealthMax();
int level1mana = ps.GetManaMax();
int level1stamina = ps.GetStaminaMax();
Assert.IsFalse(ps.AddExperience(499)); // not quite enough
Assert.IsTrue(ps.AddExperience(1)); // there we go
int level2hp = ps.GetHealthMax();
int level2mana = ps.GetManaMax();
int level2stamina = ps.GetStaminaMax();
Assert.IsFalse(ps.AddExperience(999)); // not quite enough
Assert.IsTrue(ps.AddExperience(1)); // there we go
int level3hp = ps.GetHealthMax();
int level3mana = ps.GetManaMax();
int level3stamina = ps.GetStaminaMax();
// this should update the player's health, mana, and stamina
Assert.AreEqual(level1hp + 3, level2hp);
Assert.AreEqual(level1mana + 1, level2mana);
Assert.AreEqual(level1stamina + 1, level2stamina);
Assert.AreEqual(level2hp + 3, level3hp);
Assert.AreEqual(level2mana + 2, level3mana); // because 2->3 is an odd levelup, should get 2
// more mana on this level (1.5 = +1 on even levels, +2 on odd)
Assert.AreEqual(level2stamina + 1, level3stamina);
}
}
}

View File

@ -0,0 +1,80 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenDiablo2.Common.Models.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.UT
{
[TestClass]
public class UT_Stat
{
[TestMethod]
public void BasicStatTest()
{
Stat hp = new Stat(0, 100, 100, false);
Assert.AreEqual(100, hp.GetCurrent());
Assert.AreEqual(100, hp.GetMax());
Assert.AreEqual(0, hp.GetMin());
hp.AddCurrent(10);
Assert.AreEqual(100, hp.GetCurrent()); // not allowed to go over max
hp.AddCurrent(-30);
Assert.AreEqual(70, hp.GetCurrent());
hp.SetCurrent(10);
Assert.AreEqual(10, hp.GetCurrent());
hp.AddCurrent(-30);
Assert.AreEqual(0, hp.GetCurrent()); // not allowed to go under min
}
[TestMethod]
public void ModifierStatTest()
{
Stat hp = new Stat(0, 100, 100, false);
StatModifierAddition mod1 = new StatModifierAddition("mod1", 10);
hp.AddModifier(mod1);
Assert.AreEqual(100, hp.GetCurrent()); // not allowed to overflow from mods
hp.AllowedToOverflowFromModifiers = true;
Assert.AreEqual(110, hp.GetCurrent()); // if we flip overflow to true, should overflow from mods
StatModifierAddition mod2 = new StatModifierAddition("mod2", -20);
hp.AddModifier(mod2);
Assert.AreEqual(90, hp.GetCurrent());
hp.RemoveModifier("mod1");
Assert.AreEqual(80, hp.GetCurrent()); // if we remove mod1, we should see its effect go away
hp.RemoveModifier("mod2");
Assert.AreEqual(100, hp.GetCurrent()); // similarly with mod2
}
[TestMethod]
public void ModifierPriorityTest()
{
Stat hp = new Stat(0, 100, 50, true);
StatModifierMultiplication mod1 = new StatModifierMultiplication("mod1", 0.5, priority: 1);
hp.AddModifier(mod1);
Assert.AreEqual(75, hp.GetCurrent());
StatModifierMultiplication mod2 = new StatModifierMultiplication("mod2", 0.5, priority: 1);
hp.AddModifier(mod2);
Assert.AreEqual(100, hp.GetCurrent()); // because these have the same priority,
// they don't see eachother's effects (e.g. we get 50 + 50*0.5 + 50*0.5, NOT 50 + 50*0.5 + 75*0.5
hp.RemoveModifier("mod2");
Assert.AreEqual(75, hp.GetCurrent());
StatModifierMultiplication mod3 = new StatModifierMultiplication("mod3", -0.2, priority: 0);
hp.AddModifier(mod3);
Assert.AreEqual(60, hp.GetCurrent()); // because this one has a lower priority, it happens AFTER mod1
// so we get 50 + 50*0.5 = 75, then 75 + 75*-0.2 = 60
}
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MSTest.TestAdapter" version="1.2.0" targetFramework="net461" />
<package id="MSTest.TestFramework" version="1.2.0" targetFramework="net461" />
</packages>

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Enums.Mobs
{
public enum eDamageTypes
{
NONE, // no resistances apply
PHYSICAL,
MAGIC,
FIRE,
COLD,
LIGHTNING,
POISON,
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Enums.Mobs
{
public enum eMobFlags
{
PLAYER,
ENEMY,
INVULNERABLE
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Enums.Mobs
{
public enum eStatModifierType
{
// does it affect the current value, min value, or max value?
MIN,
MAX,
CURRENT
}
}

View File

@ -1,21 +1,21 @@
namespace OpenDiablo2.Common.Enums
{
public enum eButtonType
{
Wide,
Medium,
Narrow,
Cancel,
Tall,
// Game UI
Run,
Menu,
MinipanelCharacter,
MinipanelInventory,
MinipanelSkill,
MinipanelAutomap,
MinipanelMessage,
MinipanelQuest,
MinipanelMenu
}
}
namespace OpenDiablo2.Common.Enums
{
public enum eButtonType
{
Wide,
Medium,
Narrow,
Cancel,
Tall,
// Game UI
Run,
Menu,
MinipanelCharacter,
MinipanelInventory,
MinipanelSkill,
MinipanelAutomap,
MinipanelMessage,
MinipanelQuest,
MinipanelMenu
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Enums.Mobs
{
public enum eDamageTypes
{
NONE, // no resistances apply
PHYSICAL,
MAGIC,
FIRE,
COLD,
LIGHTNING,
POISON,
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Enums.Mobs
{
public enum eMobFlags
{
PLAYER,
ENEMY,
INVULNERABLE
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Enums.Mobs
{
public enum eStatModifierType
{
// does it affect the current value, min value, or max value?
MIN,
MAX,
CURRENT
}
}

View File

@ -1,4 +1,4 @@
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Enums;
using System;
namespace OpenDiablo2.Common.Interfaces

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Interfaces.Mobs
{
public interface IHeroTypeConfig
{
int StartingVitality { get; }
int StartingStrength { get; }
int StartingDexterity { get; }
int StartingEnergy { get; }
int StartingHealth { get; }
int StartingMana { get; }
int StartingStamina { get; }
double PerLevelHealth { get; } // NOTE: these are doubles because some classes have
// e.g. 1.5 mana per level, which means they get 1 mana on even levels (e.g. -> 2)
// and 2 mana on odd levels (e.g. -> 3)
double PerLevelMana { get; }
double PerLevelStamina { get; }
double PerVitalityHealth { get; }
double PerVitalityStamina { get; }
double PerEnergyMana { get; }
int BaseAttackRating { get; }
int PerDexterityAttackRating { get; }
int BaseDefenseRating { get; }
int PerDexterityDefenseRating { get; }
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Interfaces.Mobs
{
public interface ILevelExperienceConfig
{
int GetTotalExperienceForLevel(int level);
int GetMaxLevel();
}
}

View File

@ -0,0 +1,14 @@
using OpenDiablo2.Common.Models.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Interfaces.Mobs
{
public interface IMobCondition
{
bool Evaluate(MobState mob);
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Interfaces.Mobs
{
public interface IMobManager
{
// TODO:
}
}

View File

@ -0,0 +1,19 @@
using OpenDiablo2.Common.Enums.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Interfaces.Mobs
{
public interface IStatModifier
{
string Name { get; }
int Priority { get; } // what priority does this modifier happen in? higher = occurs before other modifiers
// modifiers at the same priority level occur simultaneously
eStatModifierType ModifierType { get; } // does it affect current, min or max?
int GetValue(int min, int max, int current); // what does this modifier add to the stat's current value?
double GetValue(double min, double max, double current);
}
}

View File

@ -1,39 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenDiablo2.Common.Enums;
namespace OpenDiablo2.Common.Models
{
public class ButtonLayout
{
public int XSegments { get; internal set; }
public string ResourceName { get; internal set; }
public string PaletteName { get; internal set; }
public bool Toggleable { get; internal set; } = false;
public int BaseFrame { get; internal set; } = 0;
public static Dictionary<eButtonType, ButtonLayout> Values = new Dictionary<eButtonType, ButtonLayout>
{
{eButtonType.Wide, new ButtonLayout { XSegments = 2, ResourceName = ResourcePaths.WideButtonBlank, PaletteName = Palettes.Units } },
{eButtonType.Medium, new ButtonLayout{ XSegments = 1, ResourceName=ResourcePaths.MediumButtonBlank, PaletteName = Palettes.Units } },
{eButtonType.Narrow, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.NarrowButtonBlank,PaletteName = Palettes.Units } },
{eButtonType.Tall, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.TallButtonBlank, PaletteName = Palettes.Units } },
{eButtonType.Cancel, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.CancelButton,PaletteName = Palettes.Units } },
// Minipanel
{eButtonType.MinipanelCharacter, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 0 } },
{eButtonType.MinipanelInventory, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 2 } },
{eButtonType.MinipanelSkill, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 4 } },
{eButtonType.MinipanelAutomap, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 8 } },
{eButtonType.MinipanelMessage, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 10 } },
{eButtonType.MinipanelQuest, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 12 } },
{eButtonType.MinipanelMenu, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 14 } },
{eButtonType.Run, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.RunButton,PaletteName = Palettes.Units, Toggleable = true } },
{eButtonType.Menu, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MenuButton,PaletteName = Palettes.Units, Toggleable = true } },
};
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenDiablo2.Common.Enums;
namespace OpenDiablo2.Common.Models
{
public class ButtonLayout
{
public int XSegments { get; internal set; }
public string ResourceName { get; internal set; }
public string PaletteName { get; internal set; }
public bool Toggleable { get; internal set; } = false;
public int BaseFrame { get; internal set; } = 0;
public static Dictionary<eButtonType, ButtonLayout> Values = new Dictionary<eButtonType, ButtonLayout>
{
{eButtonType.Wide, new ButtonLayout { XSegments = 2, ResourceName = ResourcePaths.WideButtonBlank, PaletteName = Palettes.Units } },
{eButtonType.Medium, new ButtonLayout{ XSegments = 1, ResourceName=ResourcePaths.MediumButtonBlank, PaletteName = Palettes.Units } },
{eButtonType.Narrow, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.NarrowButtonBlank,PaletteName = Palettes.Units } },
{eButtonType.Tall, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.TallButtonBlank, PaletteName = Palettes.Units } },
{eButtonType.Cancel, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.CancelButton,PaletteName = Palettes.Units } },
// Minipanel
{eButtonType.MinipanelCharacter, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 0 } },
{eButtonType.MinipanelInventory, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 2 } },
{eButtonType.MinipanelSkill, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 4 } },
{eButtonType.MinipanelAutomap, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 8 } },
{eButtonType.MinipanelMessage, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 10 } },
{eButtonType.MinipanelQuest, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 12 } },
{eButtonType.MinipanelMenu, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MinipanelButton,PaletteName = Palettes.Units, BaseFrame = 14 } },
{eButtonType.Run, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.RunButton,PaletteName = Palettes.Units, Toggleable = true } },
{eButtonType.Menu, new ButtonLayout {XSegments = 1, ResourceName = ResourcePaths.MenuButton,PaletteName = Palettes.Units, Toggleable = true } },
};
}
}

View File

@ -0,0 +1,21 @@
using OpenDiablo2.Common.Enums.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Models.Mobs
{
public class EnemyState : MobState
{
public int ExperienceGiven { get; protected set; }
public EnemyState(string name, int id, int level, int maxhealth, float x, float y, int experiencegiven)
: base(name, id, level, maxhealth, x, y)
{
ExperienceGiven = experiencegiven;
AddFlag(eMobFlags.ENEMY);
}
}
}

View File

@ -0,0 +1,62 @@
using OpenDiablo2.Common.Interfaces.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Models.Mobs
{
public class HeroTypeConfig : IHeroTypeConfig
{
public int StartingVitality { get; protected set; }
public int StartingStrength { get; protected set; }
public int StartingDexterity { get; protected set; }
public int StartingEnergy { get; protected set; }
public int StartingHealth { get; protected set; }
public int StartingMana { get; protected set; }
public int StartingStamina { get; protected set; }
public double PerLevelHealth { get; protected set; }
public double PerLevelMana { get; protected set; }
public double PerLevelStamina { get; protected set; }
public double PerVitalityHealth { get; protected set; }
public double PerVitalityStamina { get; protected set; }
public double PerEnergyMana { get; protected set; }
public int BaseAttackRating { get; protected set; }
public int PerDexterityAttackRating { get; protected set; }
public int BaseDefenseRating { get; protected set; }
public int PerDexterityDefenseRating { get; protected set; }
public HeroTypeConfig(int vitality, int strength, int dexterity, int energy,
int health, int mana, int stamina,
double perlevelhealth, double perlevelmana, double perlevelstamina,
double pervitalityhealth, double pervitalitystamina, double perenergymana,
int baseatkrating, int basedefrating, int perdexterityatkrating, int perdexteritydefrating)
{
StartingDexterity = dexterity;
StartingVitality = vitality;
StartingStrength = strength;
StartingEnergy = energy;
StartingMana = mana;
StartingHealth = health;
StartingStamina = stamina;
PerLevelHealth = perlevelhealth;
PerLevelMana = perlevelmana;
PerLevelStamina = perlevelstamina;
PerVitalityHealth = pervitalityhealth;
PerVitalityStamina = pervitalitystamina;
PerEnergyMana = perenergymana;
BaseAttackRating = baseatkrating;
BaseDefenseRating = basedefrating;
PerDexterityAttackRating = perdexterityatkrating;
PerDexterityDefenseRating = perdexteritydefrating;
}
}
}

View File

@ -0,0 +1,33 @@
using OpenDiablo2.Common.Interfaces.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Models.Mobs
{
public class LevelExperienceConfig : ILevelExperienceConfig
{
private List<int> ExperiencePerLevel = new List<int>();
public LevelExperienceConfig(List<int> expperlevel)
{
ExperiencePerLevel = expperlevel;
}
public int GetTotalExperienceForLevel(int level)
{
if(ExperiencePerLevel.Count <= level)
{
return -1; // note: a value of -1 means this level is unattainable!
}
return ExperiencePerLevel[level];
}
public int GetMaxLevel()
{
return ExperiencePerLevel.Count - 1;
}
}
}

View File

@ -0,0 +1,97 @@
using OpenDiablo2.Common.Enums.Mobs;
using OpenDiablo2.Common.Interfaces.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Models.Mobs
{
public class MobConditionAnd : IMobCondition
{
public List<IMobCondition> Conditions = new List<IMobCondition>();
public MobConditionAnd(List<IMobCondition> conditions)
{
Conditions = conditions;
}
public bool Evaluate(MobState mob)
{
foreach(IMobCondition condition in Conditions)
{
if (!condition.Evaluate(mob))
{
return false;
}
}
return true;
}
}
public class MobConditionOr : IMobCondition
{
public List<IMobCondition> Conditions = new List<IMobCondition>();
public MobConditionOr(List<IMobCondition> conditions)
{
Conditions = conditions;
}
public bool Evaluate(MobState mob)
{
foreach (IMobCondition condition in Conditions)
{
if (condition.Evaluate(mob))
{
return true;
}
}
return false;
}
}
public class MobConditionNot : IMobCondition
{
public IMobCondition Condition = null;
public MobConditionNot(IMobCondition condition)
{
Condition = condition;
}
public bool Evaluate(MobState mob)
{
if(Condition == null)
{
return false;
}
return !Condition.Evaluate(mob);
}
}
public class MobConditionFlags : IMobCondition
{
public Dictionary<eMobFlags, bool> Flags = new Dictionary<eMobFlags, bool>();
public MobConditionFlags(Dictionary<eMobFlags, bool> flags)
{
Flags = flags;
}
public bool Evaluate(MobState mob)
{
foreach(eMobFlags flag in Flags.Keys)
{
if(Flags[flag] != mob.HasFlag(flag))
{
return false;
}
}
return true;
}
}
// TODO: implement more of these
}

View File

@ -0,0 +1,168 @@
using OpenDiablo2.Common.Enums.Mobs;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Models.Mobs
{
public class MobState
{
public readonly string Name;
public readonly int Id;
public bool Alive { get; protected set; } = true;
protected float X = 0;
protected float Y = 0;
protected Stat Health;
protected Dictionary<eDamageTypes, StatDouble> Resistances = new Dictionary<eDamageTypes, StatDouble>();
protected List<eDamageTypes> Immunities = new List<eDamageTypes>();
public int Level { get; protected set; }
protected Dictionary<eMobFlags, bool> Flags = new Dictionary<eMobFlags, bool>();
public MobState(string name, int id, int level, int maxhealth, float x, float y)
{
Name = name;
Id = id;
Level = level;
Health = new Stat(0, maxhealth, maxhealth, true);
X = x;
Y = y;
}
#region Position and Movement
public void Move(PointF pos)
{
Move(pos.X, pos.Y);
}
public void Move(float x, float y)
{
X = x;
Y = y;
}
public PointF GetPosition()
{
return new PointF(X, Y);
}
public float GetDistance(float x, float y)
{
// note: does not consider pathfinding!
return (float)Math.Sqrt(((X - x) * (X - x)) + ((Y - y) * (Y - y)));
}
#endregion Position and Movement
#region Combat and Damage
public void SetResistance(eDamageTypes damagetype, double val)
{
if (!Resistances.ContainsKey(damagetype))
{
Resistances.Add(damagetype, new StatDouble(0, 100.0, val, false));
}
else
{
Resistances[damagetype].SetCurrent(val);
}
}
public void AddImmunitiy(eDamageTypes damagetype)
{
if (!Immunities.Contains(damagetype))
{
Immunities.Add(damagetype);
}
}
public void RemoveImmunity(eDamageTypes damagetype)
{
if (Immunities.Contains(damagetype))
{
Immunities.Remove(damagetype);
}
}
public int GetHealth()
{
return Health.GetCurrent();
}
public int GetHealthMax()
{
return Health.GetMax();
}
public void RecoverHealth(int health)
{
Health.AddCurrent(health);
}
public int TakeDamage(int damage, eDamageTypes damagetype, MobState source = null)
{
// returns the actual amount of damage taken
damage = HandleResistances(damage, damagetype, source);
Health.AddCurrent(-1 * damage);
int newhp = Health.GetCurrent();
if(newhp <= 0)
{
Die(source);
}
return damage;
}
protected int HandleResistances(int damage, eDamageTypes damagetype, MobState source = null)
{
if(damagetype == eDamageTypes.NONE)
{
return damage;
}
if (Immunities.Contains(damagetype))
{
return 0;
}
if (!Resistances.ContainsKey(damagetype))
{
return damage;
}
// TODO: need to verify 1) is damage integer? and 2) if so, how is this rounding down?
// e.g. is it always 'round down' / 'round up' or does it use 'math.round'
damage = (int)(damage * Resistances[damagetype].GetCurrent());
return damage;
}
public void Die(MobState source = null)
{
// TODO: how do we want to tackle this?
Alive = false;
}
#endregion Combat and Damage
#region Flags
public void AddFlag(eMobFlags flag, bool on = true)
{
if (Flags.ContainsKey(flag))
{
Flags[flag] = on;
}
else
{
Flags.Add(flag, on);
}
}
public void RemoveFlag(eMobFlags flag)
{
if (Flags.ContainsKey(flag))
{
Flags.Remove(flag);
}
}
public bool HasFlag(eMobFlags flag)
{
if (Flags.ContainsKey(flag))
{
return Flags[flag];
}
return false;
}
#endregion Flags
}
}

View File

@ -0,0 +1,208 @@
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Enums.Mobs;
using OpenDiablo2.Common.Interfaces.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Models.Mobs
{
public class PlayerState : MobState
{
public eHero HeroType { get; protected set; }
private IHeroTypeConfig HeroTypeConfig;
private ILevelExperienceConfig ExperienceConfig;
// Player character stats
protected Stat Vitality;
protected Stat Strength;
protected Stat Energy;
protected Stat Dexterity;
protected Stat DefenseRating;
protected Stat AttackRating;
protected Stat Stamina;
protected Stat Mana;
public int Experience { get; protected set; }
public PlayerState(string name, int id, int level, float x, float y,
int vitality, int strength, int energy, int dexterity, int experience, eHero herotype,
IHeroTypeConfig heroconfig, ILevelExperienceConfig expconfig)
: base(name, id, level, 0, x, y)
{
Stamina = new Stat(0, 0, 0, true);
Mana = new Stat(0, 0, 0, true);
Vitality = new Stat(0, vitality, vitality, true);
Strength = new Stat(0, strength, strength, true);
Energy = new Stat(0, energy, energy, true);
Dexterity = new Stat(0, dexterity, dexterity, true);
AttackRating = new Stat(0, 0, 0, false);
DefenseRating = new Stat(0, 0, 0, false);
Experience = experience; // how much total exp do they have
HeroType = herotype;
HeroTypeConfig = heroconfig;
ExperienceConfig = expconfig;
AddFlag(eMobFlags.PLAYER);
RefreshMaxes(); // initialize the max health / mana / energy
Health.SetCurrent(Health.GetMax());
Mana.SetCurrent(Mana.GetMax());
Energy.SetCurrent(Energy.GetMax());
RefreshDerived();
}
#region Level and Experience
public int GetExperienceToLevel()
{
return GetExperienceTotalToLevel() - Experience;
}
public int GetExperienceTotalToLevel()
{
return ExperienceConfig.GetTotalExperienceForLevel(Level + 1);
}
public int GetMaxLevel()
{
return ExperienceConfig.GetMaxLevel();
}
public bool AddExperience(int amount)
{
// returns true if you level up from this
Experience += amount;
return TryLevelUp();
}
public bool TryLevelUp()
{
if(Level >= GetMaxLevel())
{
return false; // can't level up anymore
}
if(GetExperienceToLevel() > 0)
{
return false; // not enough exp
}
LevelUp();
return true;
}
public void LevelUp()
{
Level += 1;
// instead of adding to max here, let's just refresh all the maxes upon level up
//Health.AddMax(CalculatePerLevelStatIncrease(HeroTypeConfig.PerLevelHealth));
//Mana.AddMax(CalculatePerLevelStatIncrease(HeroTypeConfig.PerLevelMana));
//Stamina.AddMax(CalculatePerLevelStatIncrease(HeroTypeConfig.PerLevelStamina));
RefreshMaxes();
}
private int CalculatePerLevelStatIncrease(double increase)
{
// on even levels, e.g. 2, 4, 6, you gain 1 from an increase of 1.5
// on odd levels, you gain 2 from an increase of 1.5
return (int)(((Level % 2) * Math.Ceiling(increase)) + ((1 - (Level % 2)) * Math.Floor(increase)));
}
#endregion Level and Experience
#region Stat Calculation
public void RefreshDerived()
{
RefreshDexterityDerived();
}
// determine attack rating / defense rating
public void RefreshDexterityDerived()
{
// this needs to be called whenever dexterity changes
RefreshAttackRating();
RefreshDefenseRating();
}
public void RefreshAttackRating()
{
int atk = HeroTypeConfig.BaseAttackRating + Dexterity.GetCurrent() * HeroTypeConfig.PerDexterityAttackRating;
AttackRating.SetMax(atk);
AttackRating.SetCurrent(atk);
}
public void RefreshDefenseRating()
{
int def = HeroTypeConfig.BaseDefenseRating + Dexterity.GetCurrent() * HeroTypeConfig.PerDexterityDefenseRating;
DefenseRating.SetMax(def);
DefenseRating.SetCurrent(def);
}
// determine the max health/ mana/ stamina
public void RefreshMaxes()
{
RefreshMaxHealth();
RefreshMaxStamina();
RefreshMaxMana();
}
public void RefreshMaxHealth()
{
int health = HeroTypeConfig.StartingHealth;
health += (int)Math.Floor((Level - 1) * HeroTypeConfig.PerLevelHealth);
health += (int)Math.Floor((Vitality.GetCurrent() - HeroTypeConfig.StartingVitality) * HeroTypeConfig.PerVitalityHealth);
Health.SetMax(health);
}
public void RefreshMaxStamina()
{
int stamina = HeroTypeConfig.StartingStamina;
stamina += (int)Math.Floor((Level - 1) * HeroTypeConfig.PerLevelStamina);
stamina += (int)Math.Floor((Vitality.GetCurrent() - HeroTypeConfig.StartingVitality) * HeroTypeConfig.PerVitalityStamina);
Stamina.SetMax(stamina);
}
public void RefreshMaxMana()
{
int mana = HeroTypeConfig.StartingMana;
mana += (int)Math.Floor((Level - 1) * HeroTypeConfig.PerLevelMana);
mana += (int)Math.Floor((Energy.GetCurrent() - HeroTypeConfig.StartingEnergy) * HeroTypeConfig.PerEnergyMana);
Mana.SetMax(mana);
}
#endregion Stat Calculation
#region Mana
public int GetMana()
{
return Mana.GetCurrent();
}
public int GetManaMax()
{
return Mana.GetMax();
}
public void RecoverMana(int mana)
{
Mana.AddCurrent(mana);
}
public void UseMana(int mana)
{
Mana.AddCurrent(-mana);
}
#endregion Mana
#region Stamina
public int GetStamina()
{
return Stamina.GetCurrent();
}
public int GetStaminaMax()
{
return Stamina.GetMax();
}
public void RecoverStamina(int stamina)
{
Stamina.AddCurrent(stamina);
}
public void UseStamina(int stamina)
{
Stamina.AddCurrent(-stamina);
}
#endregion Stamina
// TODO: when a player equips an item, apply the relevant modifiers to their stats
// TODO: when a player unequips an item, remove the relevant modifiers from their stats
}
}

View File

@ -0,0 +1,159 @@
using OpenDiablo2.Common.Enums.Mobs;
using OpenDiablo2.Common.Interfaces.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Models.Mobs
{
public class Stat : StatBase
{
protected int Min = 0;
protected int Max = 0;
protected int Current = 0; // the current value BEFORE modifiers
public bool AllowedToOverflowFromModifiers = false; // if true, can return a value greater than Max
// if a modifier is increasing the current value
public Stat(int min, int max, int current, bool allowedToOverflowFromModifiers)
{
Min = min;
Max = max;
Current = current;
AllowedToOverflowFromModifiers = allowedToOverflowFromModifiers;
}
public void AddCurrent(int value)
{
Current += value;
ClampCurrent();
}
public void SetCurrent(int value)
{
Current = value;
ClampCurrent();
}
private void ClampCurrent()
{
int currentmax = GetMax();
int currentmin = GetMin();
if (Current > currentmax)
{
Current = currentmax;
}
if (Current < currentmin)
{
Current = currentmin;
}
}
public void AddMax(int value)
{
Max += value;
ClampCurrent();
}
public void SetMax(int value)
{
Max = value;
ClampCurrent();
}
public void AddMin(int value)
{
Min += value;
ClampCurrent();
}
public void SetMin(int value)
{
Min = value;
ClampCurrent();
}
public int GetCurrent()
{
int val = Current;
// take the current value and apply each modifier to it
// the modifiers are done in priority order
// OrderedModifierKeys holds the list of priorities in order from highest to lowest
// highest is operated first
// Items on the same priority level don't see eachother
// e.g. if Health is 20 and we have two modifiers with priority 5 that add 50% health,
// then we would get 20 + 10 + 10, NOT 20 + 10 + 15
// However, if one of the modifiers now has a different priority, say 4, then we would get
// 20 + 10 + 15
foreach(int k in OrderedModifierKeys)
{
int newval = val;
foreach(IStatModifier mod in Modifiers[k])
{
if(mod.ModifierType == eStatModifierType.CURRENT)
{
newval += mod.GetValue(Min, Max, val);
}
}
val = newval;
}
if (!AllowedToOverflowFromModifiers)
{
// if we aren't allowed to go over max, even with modifiers, we must double check
// that we're within our bounds
int currentmax = GetMax();
int currentmin = GetMin();
if (val > currentmax)
{
val = currentmax;
}
if (val < currentmin)
{
val = currentmin;
}
}
return val;
}
public int GetMin()
{
int val = Min;
foreach (int k in OrderedModifierKeys)
{
int newval = val;
foreach (IStatModifier mod in Modifiers[k])
{
if (mod.ModifierType == eStatModifierType.MIN)
{
newval += mod.GetValue(val, Max, Current);
}
}
val = newval;
}
return val;
}
public int GetMax()
{
int val = Max;
foreach (int k in OrderedModifierKeys)
{
int newval = val;
foreach (IStatModifier mod in Modifiers[k])
{
if (mod.ModifierType == eStatModifierType.MAX)
{
newval += mod.GetValue(Min, val, Current);
}
}
val = newval;
}
return val;
}
}
}

View File

@ -0,0 +1,77 @@
using OpenDiablo2.Common.Interfaces.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Models.Mobs
{
public abstract class StatBase
{
protected List<int> OrderedModifierKeys = new List<int>();
protected Dictionary<int, List<IStatModifier>> Modifiers = new Dictionary<int, List<IStatModifier>>();
public void AddModifier(IStatModifier mod)
{
int priority = mod.Priority;
if (!OrderedModifierKeys.Contains(priority))
{
// if this priority doesn't exist yet, create it
// we must add the new key in order of highest to lowest
int i = 0;
while (i < OrderedModifierKeys.Count)
{
if (OrderedModifierKeys[i] < priority)
{
OrderedModifierKeys.Insert(i, priority);
break;
}
i++;
}
if (i >= OrderedModifierKeys.Count)
{
OrderedModifierKeys.Add(priority);
}
Modifiers.Add(priority, new List<IStatModifier>() { mod });
}
else
{
// if priority already exists, just add it to the existing list
Modifiers[priority].Add(mod);
}
}
public void RemoveModifier(string name)
{
foreach (int k in Modifiers.Keys)
{
int i = 0;
while (i < Modifiers[k].Count)
{
IStatModifier mod = Modifiers[k][i];
if (mod.Name == name)
{
Modifiers[k].RemoveAt(i);
continue; // don't increment i
}
i++;
}
}
// now do cleanup: if any modifier list is empty, remove it and its priority
int o = 0;
while (o < Modifiers.Keys.Count)
{
int k = Modifiers.Keys.ElementAt(o);
if (Modifiers[k].Count <= 0)
{
Modifiers.Remove(k);
OrderedModifierKeys.Remove(k);
continue; // don't increment o
}
o++;
}
}
}
}

View File

@ -0,0 +1,159 @@
using OpenDiablo2.Common.Enums.Mobs;
using OpenDiablo2.Common.Interfaces.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Models.Mobs
{
public class StatDouble : StatBase
{
protected double Min = 0;
protected double Max = 0;
protected double Current = 0; // the current value BEFORE modifiers
public bool AllowedToOverflowFromModifiers = false; // if true, can return a value greater than Max
// if a modifier is increasing the current value
public StatDouble(double min, double max, double current, bool allowedToOverflowFromModifiers)
{
Min = min;
Max = max;
Current = current;
AllowedToOverflowFromModifiers = allowedToOverflowFromModifiers;
}
public void AddCurrent(double value)
{
Current += value;
ClampCurrent();
}
public void SetCurrent(double value)
{
Current = value;
ClampCurrent();
}
private void ClampCurrent()
{
double currentmax = GetMax();
double currentmin = GetMin();
if (Current > currentmax)
{
Current = currentmax;
}
if (Current < currentmin)
{
Current = currentmin;
}
}
public void AddMax(double value)
{
Max += value;
ClampCurrent();
}
public void SetMax(double value)
{
Max = value;
ClampCurrent();
}
public void AddMin(double value)
{
Min += value;
ClampCurrent();
}
public void SetMin(double value)
{
Min = value;
ClampCurrent();
}
public double GetCurrent()
{
double val = Current;
// take the current value and apply each modifier to it
// the modifiers are done in priority order
// OrderedModifierKeys holds the list of priorities in order from highest to lowest
// highest is operated first
// Items on the same priority level don't see eachother
// e.g. if Health is 20 and we have two modifiers with priority 5 that add 50% health,
// then we would get 20 + 10 + 10, NOT 20 + 10 + 15
// However, if one of the modifiers now has a different priority, say 4, then we would get
// 20 + 10 + 15
foreach (int k in OrderedModifierKeys)
{
double newval = val;
foreach (IStatModifier mod in Modifiers[k])
{
if (mod.ModifierType == eStatModifierType.CURRENT)
{
newval += mod.GetValue(Min, Max, val);
}
}
val = newval;
}
if (!AllowedToOverflowFromModifiers)
{
// if we aren't allowed to go over max, even with modifiers, we must double check
// that we're within our bounds
double currentmax = GetMax();
double currentmin = GetMin();
if (val > currentmax)
{
val = currentmax;
}
if (val < currentmin)
{
val = currentmin;
}
}
return val;
}
public double GetMin()
{
double val = Min;
foreach (int k in OrderedModifierKeys)
{
double newval = val;
foreach (IStatModifier mod in Modifiers[k])
{
if (mod.ModifierType == eStatModifierType.MIN)
{
newval += mod.GetValue(val, Max, Current);
}
}
val = newval;
}
return val;
}
public double GetMax()
{
double val = Max;
foreach (int k in OrderedModifierKeys)
{
double newval = val;
foreach (IStatModifier mod in Modifiers[k])
{
if (mod.ModifierType == eStatModifierType.MAX)
{
newval += mod.GetValue(Min, val, Current);
}
}
val = newval;
}
return val;
}
}
}

View File

@ -0,0 +1,74 @@
using OpenDiablo2.Common.Enums.Mobs;
using OpenDiablo2.Common.Interfaces.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Models.Mobs
{
public class StatModifierAddition : IStatModifier
{
public double Value = 0;
public int Priority { get; private set; }
public string Name { get; private set; }
public eStatModifierType ModifierType { get; private set; }
public StatModifierAddition(string name, double value, int priority = 0, eStatModifierType modifiertype = eStatModifierType.CURRENT)
{
Value = value;
Priority = priority;
Name = name;
ModifierType = modifiertype;
}
public int GetValue(int min, int max, int current)
{
return (int)Value;
}
public double GetValue(double min, double max, double current)
{
return Value;
}
}
public class StatModifierMultiplication : IStatModifier
{
public double Value = 0;
public int Priority { get; private set; }
public string Name { get; private set; }
public eStatModifierType ModifierType { get; private set; }
public StatModifierMultiplication(string name, double value, int priority = 0, eStatModifierType modifiertype = eStatModifierType.CURRENT)
{
Value = value;
Priority = priority;
Name = name;
ModifierType = modifiertype;
}
public int GetValue(int min, int max, int current)
{
switch (ModifierType)
{
case eStatModifierType.CURRENT:
return (int)(current * Value);
case eStatModifierType.MAX:
return (int)(max * Value);
case eStatModifierType.MIN:
return (int)(min * Value);
}
return 0; // shouldn't reach this
}
public double GetValue(double min, double max, double current)
{
switch (ModifierType)
{
case eStatModifierType.CURRENT:
return (current * Value);
case eStatModifierType.MAX:
return (max * Value);
case eStatModifierType.MIN:
return (min * Value);
}
return 0; // shouldn't reach this
}
}
}

View File

@ -1,120 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B743160E-A0BB-45DC-9998-967A85E50562}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OpenDiablo2.Common</RootNamespace>
<AssemblyName>OpenDiablo2.Common</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="DotNetZip, Version=1.12.0.0, Culture=neutral, PublicKeyToken=6583c7c814667745, processorArchitecture=MSIL">
<HintPath>..\packages\DotNetZip.1.12.0\lib\net20\DotNetZip.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.84.0.0, Culture=neutral, PublicKeyToken=1b03e6acf1164f73">
<HintPath>..\packages\NetSword.Common.ICSharpCode.SharpZipLib.0.84.0\lib\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Attributes\SceneAttribute.cs" />
<Compile Include="AutofacModule.cs" />
<Compile Include="Enums\ePanelFrameType.cs" />
<Compile Include="Enums\eButtonType.cs" />
<Compile Include="Enums\eHero.cs" />
<Compile Include="Enums\eLevelId.cs" />
<Compile Include="Enums\eLevelSubType.cs" />
<Compile Include="Enums\eMPQFormatVersion.cs" />
<Compile Include="Enums\eRenderCellType.cs" />
<Compile Include="Enums\eTextAlign.cs" />
<Compile Include="Enums\eWildBorder.cs" />
<Compile Include="Interfaces\IButton.cs" />
<Compile Include="Interfaces\IPanelFrame.cs" />
<Compile Include="Interfaces\IInventoryPanel.cs" />
<Compile Include="Interfaces\IEngineDataManager.cs" />
<Compile Include="Interfaces\IFont.cs" />
<Compile Include="Interfaces\IGameEngine.cs" />
<Compile Include="Interfaces\IGameState.cs" />
<Compile Include="Interfaces\IKeyboardInfoProvider.cs" />
<Compile Include="Interfaces\ILabel.cs" />
<Compile Include="Interfaces\IMapEngine.cs" />
<Compile Include="Interfaces\IMiniPanel.cs" />
<Compile Include="Interfaces\ICharacterPanel.cs" />
<Compile Include="Interfaces\IMouseCursor.cs" />
<Compile Include="Interfaces\IMPQProvider.cs" />
<Compile Include="Interfaces\IMusicProvider.cs" />
<Compile Include="Interfaces\IPaletteProvider.cs" />
<Compile Include="Interfaces\IRenderWindow.cs" />
<Compile Include="Interfaces\IResourceManager.cs" />
<Compile Include="Interfaces\IScene.cs" />
<Compile Include="Interfaces\ISceneManager.cs" />
<Compile Include="Interfaces\ISprite.cs" />
<Compile Include="Interfaces\IMouseInfoProvider.cs" />
<Compile Include="Interfaces\ITextBox.cs" />
<Compile Include="Interfaces\ITextDictionary.cs" />
<Compile Include="Interfaces\ITextLabel.cs" />
<Compile Include="Interfaces\ITexture.cs" />
<Compile Include="Models\BitStream.cs" />
<Compile Include="Models\ButtonLayout.cs" />
<Compile Include="Models\LevelDetail.cs" />
<Compile Include="Models\LevelPreset.cs" />
<Compile Include="Models\LevelType.cs" />
<Compile Include="Models\MapCellInfo.cs" />
<Compile Include="Models\MapInfo.cs" />
<Compile Include="Models\MPQDS1.cs" />
<Compile Include="Models\MPQDT1.cs" />
<Compile Include="Models\MPQFont.cs" />
<Compile Include="Models\GlobalConfiguration.cs" />
<Compile Include="Models\ImageSet.cs" />
<Compile Include="Models\MPQ.cs" />
<Compile Include="Models\MPQHuffman.cs" />
<Compile Include="Models\MPQStream.cs" />
<Compile Include="Models\MPQWavCompression.cs" />
<Compile Include="Models\Palette.cs" />
<Compile Include="Models\PKLibDecompress.cs" />
<Compile Include="Models\SoundEntry.cs" />
<Compile Include="Palettes.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ResourcePaths.cs" />
<Compile Include="StringUtils.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B743160E-A0BB-45DC-9998-967A85E50562}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OpenDiablo2.Common</RootNamespace>
<AssemblyName>OpenDiablo2.Common</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="DotNetZip, Version=1.12.0.0, Culture=neutral, PublicKeyToken=6583c7c814667745, processorArchitecture=MSIL">
<HintPath>..\packages\DotNetZip.1.12.0\lib\net20\DotNetZip.dll</HintPath>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.84.0.0, Culture=neutral, PublicKeyToken=1b03e6acf1164f73">
<HintPath>..\packages\NetSword.Common.ICSharpCode.SharpZipLib.0.84.0\lib\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Attributes\SceneAttribute.cs" />
<Compile Include="AutofacModule.cs" />
<Compile Include="Enums\ePanelFrameType.cs" />
<Compile Include="Enums\eButtonType.cs" />
<Compile Include="Enums\eHero.cs" />
<Compile Include="Enums\eLevelId.cs" />
<Compile Include="Enums\eLevelSubType.cs" />
<Compile Include="Enums\eMPQFormatVersion.cs" />
<Compile Include="Enums\eRenderCellType.cs" />
<Compile Include="Enums\eTextAlign.cs" />
<Compile Include="Enums\eWildBorder.cs" />
<Compile Include="Enums\Mobs\eDamageTypes.cs" />
<Compile Include="Enums\Mobs\eMobFlags.cs" />
<Compile Include="Enums\Mobs\eStatModifierType.cs" />
<Compile Include="Interfaces\IButton.cs" />
<Compile Include="Interfaces\IPanelFrame.cs" />
<Compile Include="Interfaces\IInventoryPanel.cs" />
<Compile Include="Interfaces\IEngineDataManager.cs" />
<Compile Include="Interfaces\IFont.cs" />
<Compile Include="Interfaces\IGameEngine.cs" />
<Compile Include="Interfaces\IGameState.cs" />
<Compile Include="Interfaces\IKeyboardInfoProvider.cs" />
<Compile Include="Interfaces\ILabel.cs" />
<Compile Include="Interfaces\IMapEngine.cs" />
<Compile Include="Interfaces\IMiniPanel.cs" />
<Compile Include="Interfaces\ICharacterPanel.cs" />
<Compile Include="Interfaces\IMouseCursor.cs" />
<Compile Include="Interfaces\IMPQProvider.cs" />
<Compile Include="Interfaces\IMusicProvider.cs" />
<Compile Include="Interfaces\IPaletteProvider.cs" />
<Compile Include="Interfaces\IRenderWindow.cs" />
<Compile Include="Interfaces\IResourceManager.cs" />
<Compile Include="Interfaces\IScene.cs" />
<Compile Include="Interfaces\ISceneManager.cs" />
<Compile Include="Interfaces\ISprite.cs" />
<Compile Include="Interfaces\IMouseInfoProvider.cs" />
<Compile Include="Interfaces\ITextBox.cs" />
<Compile Include="Interfaces\ITextDictionary.cs" />
<Compile Include="Interfaces\ITextLabel.cs" />
<Compile Include="Interfaces\ITexture.cs" />
<Compile Include="Interfaces\Mobs\IHeroTypeConfig.cs" />
<Compile Include="Interfaces\Mobs\ILevelExperienceConfig.cs" />
<Compile Include="Interfaces\Mobs\IMobCondition.cs" />
<Compile Include="Interfaces\Mobs\IMobManager.cs" />
<Compile Include="Interfaces\Mobs\IStatModifier.cs" />
<Compile Include="Models\BitStream.cs" />
<Compile Include="Models\ButtonLayout.cs" />
<Compile Include="Models\LevelDetail.cs" />
<Compile Include="Models\LevelPreset.cs" />
<Compile Include="Models\LevelType.cs" />
<Compile Include="Models\MapCellInfo.cs" />
<Compile Include="Models\MapInfo.cs" />
<Compile Include="Models\Mobs\EnemyState.cs" />
<Compile Include="Models\Mobs\HeroTypeConfig.cs" />
<Compile Include="Models\Mobs\LevelExperienceConfig.cs" />
<Compile Include="Models\Mobs\MobCondition.cs" />
<Compile Include="Models\Mobs\MobState.cs" />
<Compile Include="Models\Mobs\PlayerState.cs" />
<Compile Include="Models\Mobs\Stat.cs" />
<Compile Include="Models\Mobs\StatBase.cs" />
<Compile Include="Models\Mobs\StatDouble.cs" />
<Compile Include="Models\Mobs\StatModifier.cs" />
<Compile Include="Models\MPQDS1.cs" />
<Compile Include="Models\MPQDT1.cs" />
<Compile Include="Models\MPQFont.cs" />
<Compile Include="Models\GlobalConfiguration.cs" />
<Compile Include="Models\ImageSet.cs" />
<Compile Include="Models\MPQ.cs" />
<Compile Include="Models\MPQHuffman.cs" />
<Compile Include="Models\MPQStream.cs" />
<Compile Include="Models\MPQWavCompression.cs" />
<Compile Include="Models\Palette.cs" />
<Compile Include="Models\PKLibDecompress.cs" />
<Compile Include="Models\SoundEntry.cs" />
<Compile Include="Palettes.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ResourcePaths.cs" />
<Compile Include="StringUtils.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -3,7 +3,7 @@
<Import Project="..\packages\MSTest.TestAdapter.1.2.0\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.1.2.0\build\net45\MSTest.TestAdapter.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Platform Condition=" '$(Platform)' == '' ">x64</Platform>
<ProjectGuid>{F187FACE-CBA2-4012-8308-06CCDC9D6AB1}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
@ -20,7 +20,7 @@
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
@ -30,7 +30,7 @@
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
@ -49,8 +49,8 @@
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="UT_EngineDataManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UT_MobManager.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View File

@ -0,0 +1,72 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenDiablo2.Common.Enums.Mobs;
using OpenDiablo2.Common.Models.Mobs;
using OpenDiablo2.Core.GameState_;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Core.UT
{
[TestClass]
public class UT_MobManager
{
[TestMethod]
public void FindMobsTest()
{
MobManager mobman = new MobManager();
MobState mob1 = new MobState("test1", mobman.GetNextAvailableMobId(), 1, 100, 0, 0);
MobState mob2 = new MobState("test2", mobman.GetNextAvailableMobId(), 1, 100, 0, 0);
MobState mob3 = new MobState("test3", mobman.GetNextAvailableMobId(), 1, 100, 0, 0);
mob1.AddFlag(eMobFlags.ENEMY);
mob2.AddFlag(eMobFlags.ENEMY);
mob2.AddFlag(eMobFlags.INVULNERABLE);
mobman.AddMob(mob1);
mobman.AddMob(mob2);
mobman.AddMob(mob3);
Assert.IsTrue(mobman.FindMobs(new MobConditionFlags(
new Dictionary<eMobFlags, bool> {
{ eMobFlags.ENEMY, true }
})).Count == 2);
Assert.IsTrue(mobman.FindMobs(new MobConditionFlags(
new Dictionary<eMobFlags, bool> {
{ eMobFlags.INVULNERABLE, true }
})).Count == 1);
Assert.IsTrue(mobman.FindMobs(new MobConditionFlags(
new Dictionary<eMobFlags, bool> {
{ eMobFlags.PLAYER, true }
})).Count == 0);
Assert.IsTrue(mobman.FindMobs(new MobConditionFlags(
new Dictionary<eMobFlags, bool> {
{ eMobFlags.PLAYER, false }
})).Count == 3);
}
[TestMethod]
public void FindMobsInRadiusTest()
{
MobManager mobman = new MobManager();
MobState mob1 = new MobState("test1", mobman.GetNextAvailableMobId(), 1, 100, 0, 0);
MobState mob2 = new MobState("test2", mobman.GetNextAvailableMobId(), 1, 100, 10, 10);
MobState mob3 = new MobState("test3", mobman.GetNextAvailableMobId(), 1, 100, 3, 1);
mob1.AddFlag(eMobFlags.ENEMY);
mob2.AddFlag(eMobFlags.ENEMY);
mob2.AddFlag(eMobFlags.INVULNERABLE);
mobman.AddMob(mob1);
mobman.AddMob(mob2);
mobman.AddMob(mob3);
Assert.IsTrue(mobman.FindMobsInRadius(0, 0, 1, null).Count == 1);
Assert.IsTrue(mobman.FindMobsInRadius(0, 0, 7, null).Count == 2);
Assert.IsTrue(mobman.FindMobsInRadius(0, 0, 20, null).Count == 3);
Assert.IsTrue(mobman.FindMobsInRadius(10, 10, 1, null).Count == 1);
}
}
}

View File

@ -226,18 +226,18 @@ namespace OpenDiablo2.Core.GameState_
}
public bool ToggleShowInventoryPanel()
{
ShowInventoryPanel = !ShowInventoryPanel;
return ShowInventoryPanel;
public bool ToggleShowInventoryPanel()
{
ShowInventoryPanel = !ShowInventoryPanel;
return ShowInventoryPanel;
}
public bool ToggleShowCharacterPanel()
{
ShowCharacterPanel = !ShowCharacterPanel;
return ShowCharacterPanel;
public bool ToggleShowCharacterPanel()
{
ShowCharacterPanel = !ShowCharacterPanel;
return ShowCharacterPanel;
}

View File

@ -0,0 +1,141 @@
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces.Mobs;
using OpenDiablo2.Common.Models.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Core.GameState_
{
public class MobManager : IMobManager
{
private List<MobState> Mobs = new List<MobState>(); // all mobs (including players!)
private List<PlayerState> Players = new List<PlayerState>();
private List<EnemyState> Enemies = new List<EnemyState>();
private List<int> IdsUsed = new List<int>();
#region Player Controls
public void AddPlayer(PlayerState player)
{
Players.Add(player);
AddMob(player);
}
public void RemovePlayer(PlayerState player)
{
Players.Remove(player);
RemoveMob(player);
}
#endregion Player Controls
#region Mob Controls
public void AddMob(MobState mob)
{
Mobs.Add(mob);
// add id to idsused in order
int i = 0;
while(i < IdsUsed.Count)
{
if(IdsUsed[i] > mob.Id)
{
IdsUsed.Insert(i, mob.Id);
break;
}
i++;
}
if(i == IdsUsed.Count)
{
// didn't get added
IdsUsed.Add(mob.Id);
}
}
public void RemoveMob(MobState mob)
{
Mobs.Remove(mob);
IdsUsed.Remove(mob.Id);
}
public int GetNextAvailableMobId()
{
int i = 0;
while(i < IdsUsed.Count)
{
if(IdsUsed[i] != i)
{
return i;
}
i++;
}
return IdsUsed.Count;
}
#endregion Mob Controls
#region Enemy Controls
public void AddEnemy(EnemyState enemy)
{
Enemies.Add(enemy);
AddMob(enemy);
}
public void RemoveEnemy(EnemyState enemy)
{
Enemies.Remove(enemy);
RemoveMob(enemy);
}
#endregion Enemy Controls
#region Searching and Filtering
public List<MobState> FilterMobs(IEnumerable<MobState> mobs, IMobCondition condition)
{
// note: if condition is null, returns full list
List<MobState> filtered = new List<MobState>();
foreach(MobState mob in mobs)
{
if (condition == null || condition.Evaluate(mob))
{
filtered.Add(mob);
}
}
return filtered;
}
public List<MobState> FindMobs(IMobCondition condition)
{
return FilterMobs(Mobs, condition);
}
public List<MobState> FindEnemies(IMobCondition condition)
{
return FilterMobs(Enemies, condition);
}
public List<MobState> FindPlayers(IMobCondition condition)
{
return FilterMobs(Players, condition);
}
public List<MobState> FindInRadius(IEnumerable<MobState> mobs, float centerx, float centery, float radius)
{
List<MobState> filtered = new List<MobState>();
foreach(MobState mob in mobs)
{
if(mob.GetDistance(centerx, centery) <= radius)
{
filtered.Add(mob);
}
}
return filtered;
}
public List<MobState> FindMobsInRadius(float centerx, float centery, float radius, IMobCondition condition)
{
return FilterMobs(FindInRadius(Mobs, centerx, centery, radius), condition);
}
public List<MobState> FindEnemiesInRadius(float centerx, float centery, float radius, IMobCondition condition)
{
return FilterMobs(FindInRadius(Enemies, centerx, centery, radius), condition);
}
public List<MobState> FindPlayersInRadius(float centerx, float centery, float radius, IMobCondition condition)
{
return FilterMobs(FindInRadius(Players, centerx, centery, radius), condition);
}
#endregion Searching and Filtering
}
}

View File

@ -1,85 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8FC6BF7D-835A-47C1-A6B2-125495FA0900}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OpenDiablo2.Core</RootNamespace>
<AssemblyName>OpenDiablo2.Core</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Autofac, Version=4.8.1.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<HintPath>..\packages\Autofac.4.8.1\lib\net45\Autofac.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="Xabe.FFmpeg, Version=3.1.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xabe.FFmpeg.3.1.4\lib\netstandard2.0\Xabe.FFmpeg.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AutofacModule.cs" />
<Compile Include="EngineDataManager.cs" />
<Compile Include="GameEngine.cs" />
<Compile Include="GameState\GameState.cs" />
<Compile Include="Map Engine\MapEngine.cs" />
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8FC6BF7D-835A-47C1-A6B2-125495FA0900}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OpenDiablo2.Core</RootNamespace>
<AssemblyName>OpenDiablo2.Core</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Autofac, Version=4.8.1.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<HintPath>..\packages\Autofac.4.8.1\lib\net45\Autofac.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="Xabe.FFmpeg, Version=3.1.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Xabe.FFmpeg.3.1.4\lib\netstandard2.0\Xabe.FFmpeg.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AutofacModule.cs" />
<Compile Include="EngineDataManager.cs" />
<Compile Include="GameEngine.cs" />
<Compile Include="GameState\GameState.cs" />
<Compile Include="GameState\MobManager.cs" />
<Compile Include="Map Engine\MapEngine.cs" />
<Compile Include="Map Engine\MapGenerator.cs" />
<Compile Include="MPQProvider.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ResourceManager.cs" />
<Compile Include="TextDictionary.cs" />
<Compile Include="UI\Button.cs" />
<Compile Include="UI\PanelFrame.cs" />
<Compile Include="UI\InventoryPanel.cs" />
<Compile Include="UI\TextBox.cs" />
<Compile Include="UI\MiniPanel.cs" />
<Compile Include="UI\CharacterPanel.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenDiablo2.Common\OpenDiablo2.Common.csproj">
<Project>{b743160e-a0bb-45dc-9998-967a85e50562}</Project>
<Name>OpenDiablo2.Common</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Compile Include="MPQProvider.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ResourceManager.cs" />
<Compile Include="TextDictionary.cs" />
<Compile Include="UI\Button.cs" />
<Compile Include="UI\PanelFrame.cs" />
<Compile Include="UI\InventoryPanel.cs" />
<Compile Include="UI\TextBox.cs" />
<Compile Include="UI\MiniPanel.cs" />
<Compile Include="UI\CharacterPanel.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenDiablo2.Common\OpenDiablo2.Common.csproj">
<Project>{b743160e-a0bb-45dc-9998-967a85e50562}</Project>
<Name>OpenDiablo2.Common</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,44 +1,44 @@
using System;
using System.Drawing;
using OpenDiablo2.Common;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
namespace OpenDiablo2.Core.UI
{
public sealed class CharacterPanel : ICharacterPanel
{
private readonly IRenderWindow renderWindow;
private ISprite sprite;
private IPanelFrame panelFrame;
public Point Location { get; set; }
public CharacterPanel(IRenderWindow renderWindow, Func<ePanelFrameType, IPanelFrame> createPanelFrame)
{
this.renderWindow = renderWindow;
this.panelFrame = createPanelFrame(ePanelFrameType.Left);
sprite = renderWindow.LoadSprite(ResourcePaths.InventoryCharacterPanel, Palettes.Units, new Point(79,61));
Location = new Point(0, 0);
}
public void Update()
{
}
public void Render()
{
panelFrame.Render();
renderWindow.Draw(sprite, 2, 2, 0);
}
public void Dispose()
{
sprite.Dispose();
}
}
}
using System;
using System.Drawing;
using OpenDiablo2.Common;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
namespace OpenDiablo2.Core.UI
{
public sealed class CharacterPanel : ICharacterPanel
{
private readonly IRenderWindow renderWindow;
private ISprite sprite;
private IPanelFrame panelFrame;
public Point Location { get; set; }
public CharacterPanel(IRenderWindow renderWindow, Func<ePanelFrameType, IPanelFrame> createPanelFrame)
{
this.renderWindow = renderWindow;
this.panelFrame = createPanelFrame(ePanelFrameType.Left);
sprite = renderWindow.LoadSprite(ResourcePaths.InventoryCharacterPanel, Palettes.Units, new Point(79,61));
Location = new Point(0, 0);
}
public void Update()
{
}
public void Render()
{
panelFrame.Render();
renderWindow.Draw(sprite, 2, 2, 0);
}
public void Dispose()
{
sprite.Dispose();
}
}
}

View File

@ -1,42 +1,42 @@
using System;
using System.Drawing;
using OpenDiablo2.Common;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
namespace OpenDiablo2.Core.UI
{
public sealed class InventoryPanel : IInventoryPanel
{
private readonly IRenderWindow renderWindow;
private ISprite sprite;
private IPanelFrame panelFrame;
public Point Location { get; set; }
public InventoryPanel(Func<ePanelFrameType, IPanelFrame> createPanelFrame, IRenderWindow renderWindow)
{
this.renderWindow = renderWindow;
this.panelFrame = createPanelFrame(ePanelFrameType.Right);
sprite = renderWindow.LoadSprite(ResourcePaths.InventoryCharacterPanel, Palettes.Units, new Point(402,61));
Location = new Point(400, 0);
}
public void Update()
{
}
public void Render()
{
panelFrame.Render();
renderWindow.Draw(sprite, 2, 2, 1);
}
public void Dispose()
{
sprite.Dispose();
}
}
}
using System;
using System.Drawing;
using OpenDiablo2.Common;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
namespace OpenDiablo2.Core.UI
{
public sealed class InventoryPanel : IInventoryPanel
{
private readonly IRenderWindow renderWindow;
private ISprite sprite;
private IPanelFrame panelFrame;
public Point Location { get; set; }
public InventoryPanel(Func<ePanelFrameType, IPanelFrame> createPanelFrame, IRenderWindow renderWindow)
{
this.renderWindow = renderWindow;
this.panelFrame = createPanelFrame(ePanelFrameType.Right);
sprite = renderWindow.LoadSprite(ResourcePaths.InventoryCharacterPanel, Palettes.Units, new Point(402,61));
Location = new Point(400, 0);
}
public void Update()
{
}
public void Render()
{
panelFrame.Render();
renderWindow.Draw(sprite, 2, 2, 1);
}
public void Dispose()
{
sprite.Dispose();
}
}
}

View File

@ -1,101 +1,101 @@
using System;
using System.Drawing;
using OpenDiablo2.Common;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
namespace OpenDiablo2.Core.UI
{
// TODO: Self-align when side panels are open
public sealed class MiniPanel : IMiniPanel
{
private readonly IRenderWindow renderWindow;
private ISprite sprite;
private IButton characterBtn, inventoryBtn, skillBtn, automapBtn, messageBtn, questBtn, menuBtn;
private Point location = new Point();
public Point Location
{
get => location;
set
{
if (location == value)
return;
location = value;
sprite.Location = new Point(value.X, value.Y + sprite.LocalFrameSize.Height);
}
}
public MiniPanel(IRenderWindow renderWindow, IGameState gameState, Func<eButtonType, IButton> createButton)
{
this.renderWindow = renderWindow;
sprite = renderWindow.LoadSprite(ResourcePaths.MinipanelSmall, Palettes.Units);
Location = new Point(800/2-sprite.LocalFrameSize.Width/2, 526);
characterBtn = createButton(eButtonType.MinipanelCharacter);
characterBtn.Location = new Point(3 + Location.X, 3 + Location.Y);
characterBtn.OnActivate = () => gameState.ToggleShowCharacterPanel();
inventoryBtn = createButton(eButtonType.MinipanelInventory);
inventoryBtn.Location = new Point(24 + Location.X, 3 + Location.Y);
inventoryBtn.OnActivate = () => gameState.ToggleShowInventoryPanel();
skillBtn = createButton(eButtonType.MinipanelSkill);
skillBtn.Location = new Point(45 + Location.X, 3 + Location.Y);
automapBtn = createButton(eButtonType.MinipanelAutomap);
automapBtn.Location = new Point(66 + Location.X, 3 + Location.Y);
messageBtn = createButton(eButtonType.MinipanelMessage);
messageBtn.Location = new Point(87 + Location.X, 3 + Location.Y);
questBtn = createButton(eButtonType.MinipanelQuest);
questBtn.Location = new Point(108 + Location.X, 3 + Location.Y);
menuBtn = createButton(eButtonType.MinipanelMenu);
menuBtn.Location = new Point(129 + Location.X, 3 + Location.Y);
}
public void Update()
{
characterBtn.Update();
inventoryBtn.Update();
skillBtn.Update();
automapBtn.Update();
messageBtn.Update();
questBtn.Update();
menuBtn.Update();
}
public void Render()
{
renderWindow.Draw(sprite);
characterBtn.Render();
inventoryBtn.Render();
skillBtn.Render();
automapBtn.Render();
messageBtn.Render();
questBtn.Render();
menuBtn.Render();
}
public void Dispose()
{
characterBtn.Dispose();
inventoryBtn.Dispose();
skillBtn.Dispose();
automapBtn.Dispose();
messageBtn.Dispose();
questBtn.Dispose();
menuBtn.Dispose();
sprite.Dispose();
}
}
}
using System;
using System.Drawing;
using OpenDiablo2.Common;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
namespace OpenDiablo2.Core.UI
{
// TODO: Self-align when side panels are open
public sealed class MiniPanel : IMiniPanel
{
private readonly IRenderWindow renderWindow;
private ISprite sprite;
private IButton characterBtn, inventoryBtn, skillBtn, automapBtn, messageBtn, questBtn, menuBtn;
private Point location = new Point();
public Point Location
{
get => location;
set
{
if (location == value)
return;
location = value;
sprite.Location = new Point(value.X, value.Y + sprite.LocalFrameSize.Height);
}
}
public MiniPanel(IRenderWindow renderWindow, IGameState gameState, Func<eButtonType, IButton> createButton)
{
this.renderWindow = renderWindow;
sprite = renderWindow.LoadSprite(ResourcePaths.MinipanelSmall, Palettes.Units);
Location = new Point(800/2-sprite.LocalFrameSize.Width/2, 526);
characterBtn = createButton(eButtonType.MinipanelCharacter);
characterBtn.Location = new Point(3 + Location.X, 3 + Location.Y);
characterBtn.OnActivate = () => gameState.ToggleShowCharacterPanel();
inventoryBtn = createButton(eButtonType.MinipanelInventory);
inventoryBtn.Location = new Point(24 + Location.X, 3 + Location.Y);
inventoryBtn.OnActivate = () => gameState.ToggleShowInventoryPanel();
skillBtn = createButton(eButtonType.MinipanelSkill);
skillBtn.Location = new Point(45 + Location.X, 3 + Location.Y);
automapBtn = createButton(eButtonType.MinipanelAutomap);
automapBtn.Location = new Point(66 + Location.X, 3 + Location.Y);
messageBtn = createButton(eButtonType.MinipanelMessage);
messageBtn.Location = new Point(87 + Location.X, 3 + Location.Y);
questBtn = createButton(eButtonType.MinipanelQuest);
questBtn.Location = new Point(108 + Location.X, 3 + Location.Y);
menuBtn = createButton(eButtonType.MinipanelMenu);
menuBtn.Location = new Point(129 + Location.X, 3 + Location.Y);
}
public void Update()
{
characterBtn.Update();
inventoryBtn.Update();
skillBtn.Update();
automapBtn.Update();
messageBtn.Update();
questBtn.Update();
menuBtn.Update();
}
public void Render()
{
renderWindow.Draw(sprite);
characterBtn.Render();
inventoryBtn.Render();
skillBtn.Render();
automapBtn.Render();
messageBtn.Render();
questBtn.Render();
menuBtn.Render();
}
public void Dispose()
{
characterBtn.Dispose();
inventoryBtn.Dispose();
skillBtn.Dispose();
automapBtn.Dispose();
messageBtn.Dispose();
questBtn.Dispose();
menuBtn.Dispose();
sprite.Dispose();
}
}
}

View File

@ -1,67 +1,67 @@
using System;
using System.Drawing;
using OpenDiablo2.Common;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
namespace OpenDiablo2.Core.UI
{
public sealed class PanelFrame : IPanelFrame
{
private readonly IRenderWindow renderWindow;
private ISprite sprite;
private ePanelFrameType panelFrameType;
public Point Location { get; set; }
public PanelFrame(IRenderWindow renderWindow, ePanelFrameType panelFrameType)
{
this.renderWindow = renderWindow;
this.panelFrameType = panelFrameType;
sprite = renderWindow.LoadSprite(ResourcePaths.Frame, Palettes.Units, new Point(0, 0));
Location = new Point(0, 0);
}
private void DrawPanel()
{
switch(this.panelFrameType)
{
case ePanelFrameType.Left:
renderWindow.Draw(sprite, 0, new Point(0, 256));
renderWindow.Draw(sprite, 1, new Point(256, 66));
renderWindow.Draw(sprite, 2, new Point(0, 256 + 231));
renderWindow.Draw(sprite, 3, new Point(0, 256 + 231 + 66));
renderWindow.Draw(sprite, 4, new Point(256, 256 + 231 + 66));
break;
case ePanelFrameType.Right:
renderWindow.Draw(sprite, 5, new Point(400 + 0, 66));
renderWindow.Draw(sprite, 6, new Point(400 + 145, 256));
renderWindow.Draw(sprite, 7, new Point(400 + 145 + 169, 256 + 231));
renderWindow.Draw(sprite, 8, new Point(400 + 145, 256 + 231 + 66));
renderWindow.Draw(sprite, 9, new Point(400 + 0, 256 + 231 + 66));
break;
}
}
public void Update()
{
}
public void Render()
{
DrawPanel();
}
public void Dispose()
{
sprite.Dispose();
}
}
}
using System;
using System.Drawing;
using OpenDiablo2.Common;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
namespace OpenDiablo2.Core.UI
{
public sealed class PanelFrame : IPanelFrame
{
private readonly IRenderWindow renderWindow;
private ISprite sprite;
private ePanelFrameType panelFrameType;
public Point Location { get; set; }
public PanelFrame(IRenderWindow renderWindow, ePanelFrameType panelFrameType)
{
this.renderWindow = renderWindow;
this.panelFrameType = panelFrameType;
sprite = renderWindow.LoadSprite(ResourcePaths.Frame, Palettes.Units, new Point(0, 0));
Location = new Point(0, 0);
}
private void DrawPanel()
{
switch(this.panelFrameType)
{
case ePanelFrameType.Left:
renderWindow.Draw(sprite, 0, new Point(0, 256));
renderWindow.Draw(sprite, 1, new Point(256, 66));
renderWindow.Draw(sprite, 2, new Point(0, 256 + 231));
renderWindow.Draw(sprite, 3, new Point(0, 256 + 231 + 66));
renderWindow.Draw(sprite, 4, new Point(256, 256 + 231 + 66));
break;
case ePanelFrameType.Right:
renderWindow.Draw(sprite, 5, new Point(400 + 0, 66));
renderWindow.Draw(sprite, 6, new Point(400 + 145, 256));
renderWindow.Draw(sprite, 7, new Point(400 + 145 + 169, 256 + 231));
renderWindow.Draw(sprite, 8, new Point(400 + 145, 256 + 231 + 66));
renderWindow.Draw(sprite, 9, new Point(400 + 0, 256 + 231 + 66));
break;
}
}
public void Update()
{
}
public void Render()
{
DrawPanel();
}
public void Dispose()
{
sprite.Dispose();
}
}
}

View File

@ -15,6 +15,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenDiablo2.Scenes", "OpenD
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenDiablo2.TestConsole", "OpenDiablo2.TestConsole\OpenDiablo2.TestConsole.csproj", "{40BD2DDE-DC6F-4F6D-9050-9B423C631192}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenDiablo2.Common.UT", "OpenDiablo2.Common.UT\OpenDiablo2.Common.UT.csproj", "{77B00705-A2A5-4675-9A16-1FAB2692151B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenDiablo2.Core.UT", "OpenDiablo2.Core.UT\OpenDiablo2.Core.UT.csproj", "{F187FACE-CBA2-4012-8308-06CCDC9D6AB1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utilities", "Utilities", "{A1AAF640-AEFB-48E7-8BCE-E01D287B5286}"
EndProject
Global
@ -47,6 +51,14 @@ Global
{40BD2DDE-DC6F-4F6D-9050-9B423C631192}.Debug|x64.Build.0 = Debug|x64
{40BD2DDE-DC6F-4F6D-9050-9B423C631192}.Release|x64.ActiveCfg = Release|x64
{40BD2DDE-DC6F-4F6D-9050-9B423C631192}.Release|x64.Build.0 = Release|x64
{77B00705-A2A5-4675-9A16-1FAB2692151B}.Debug|x64.ActiveCfg = Debug|x64
{77B00705-A2A5-4675-9A16-1FAB2692151B}.Debug|x64.Build.0 = Debug|x64
{77B00705-A2A5-4675-9A16-1FAB2692151B}.Release|x64.ActiveCfg = Release|x64
{77B00705-A2A5-4675-9A16-1FAB2692151B}.Release|x64.Build.0 = Release|x64
{F187FACE-CBA2-4012-8308-06CCDC9D6AB1}.Debug|x64.ActiveCfg = Debug|x64
{F187FACE-CBA2-4012-8308-06CCDC9D6AB1}.Debug|x64.Build.0 = Debug|x64
{F187FACE-CBA2-4012-8308-06CCDC9D6AB1}.Release|x64.ActiveCfg = Release|x64
{F187FACE-CBA2-4012-8308-06CCDC9D6AB1}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE