1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-06-20 14:15:23 +00:00

Inventory based on hero type (#43)

* (Try to) Render inventory based on initial equipment for each hero type
This commit is contained in:
Diego M 2018-12-11 02:25:41 -03:00 committed by GitHub
parent dbd3e0b74f
commit 443fea069d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 258 additions and 98 deletions

View File

@ -1,4 +1,6 @@
namespace OpenDiablo2.Common.Enums
using System.Collections.Generic;
namespace OpenDiablo2.Common.Enums
{
public enum eItemContainerType
{
@ -12,4 +14,4 @@
Ring,
Generic
}
}
}

View File

@ -12,7 +12,6 @@
MoveRequest = 0x06,
PlayerMove = 0x07,
MAX = 0xFF, // NOTE:
// You absolutely cannot have a higher ID than this without
// changing the message header to multi-byte for ALL frame types!!!

View File

@ -19,7 +19,7 @@ namespace OpenDiablo2.Common.Interfaces
MPQDS1 GetMPQDS1(string resourcePath, LevelPreset level, LevelType levelType);
MPQDT1 GetMPQDT1(string resourcePath);
Palette GetPalette(string paletteFile);
MPQCOF GetPlayerAnimation(eHero hero, eWeaponClass weaponClass, eMobMode mobMode);
MPQCOF GetPlayerAnimation(eHero hero, eWeaponClass weaponClass, eMobMode mobMode, string ShieldCode, string weaponCode);
MPQDCC GetPlayerDCC(MPQCOF.COFLayer cofLayer, eArmorType armorType, Palette palette);
Dictionary<string, List<AnimationData>> Animations { get; }

View File

@ -11,8 +11,10 @@ namespace OpenDiablo2.Common.Interfaces.Drawing
eHero Hero { get; set; }
eWeaponClass WeaponClass { get; set; }
eArmorType ArmorType { get; set; }
eMobMode MobMode { get; set; }
eMobMode MobMode { get; set; }
string ShieldCode { get; set; }
string WeaponCode { get; set; }
void Update(long ms);
void Render(int pixelOffsetX, int pixelOffsetY);
void ResetAnimationData();

View File

@ -16,8 +16,8 @@ namespace OpenDiablo2.Common.Interfaces
Palette CurrentPalette { get; }
IEnumerable<PlayerInfo> PlayerInfos { get; }
Item SelectedItem { get; }
void SelectItem(Item item);
ItemInstance SelectedItem { get; }
void SelectItem(ItemInstance item);
int CameraOffset { get; set; }

View File

@ -0,0 +1,30 @@
/* OpenDiablo 2 - An open source re-implementation of Diablo 2 in C#
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using OpenDiablo2.Common.Models;
using System;
using System.Runtime.Caching;
namespace OpenDiablo2.Common.Interfaces
{
public interface IItemInstance
{
Item Item { get; }
string Name { get; }
int Level { get; }
bool Identified { get; }
}
}

View File

@ -6,5 +6,6 @@ namespace OpenDiablo2.Common.Interfaces
public interface IItemManager
{
Item getItem(string code);
ItemInstance getItemInstance(string code);
}
}

View File

@ -1,4 +1,5 @@
using System;
using OpenDiablo2.Common.Models.Mobs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -47,8 +48,6 @@ namespace OpenDiablo2.Common.Interfaces.Mobs
int StartingSkill { get; }
string BaseWeaponClass { get; }
IEnumerable<string> ItemNames { get; }
IEnumerable<string> ItemLocs { get; }
IEnumerable<int> ItemCounts { get; }
List<InitialEquipment> InitialEquipment { get; }
}
}

View File

@ -6,10 +6,10 @@ namespace OpenDiablo2.Common.Interfaces
{
public interface IItemContainer : IDisposable
{
Item ContainedItem { get; }
ItemInstance ContainedItem { get; }
Point Location { get; set; }
void SetContainedItem(Item containedItem);
void SetContainedItem(ItemInstance containedItem);
void Render();
void Update();
}

View File

@ -1,4 +1,5 @@
using OpenDiablo2.Common.Interfaces;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
@ -9,7 +10,7 @@ namespace OpenDiablo2.Common.Models
{
public sealed class Armor : Item
{
public string Type { get; internal set; }
}
public static class ArmorHelper

View File

@ -0,0 +1,25 @@
using OpenDiablo2.Common.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenDiablo2.Common.Models
{
/**
* Base Item class, contains common attributes for all item types.
**/
public class ItemInstance : IItemInstance
{
public Item Item { get; internal set; }
public string Name { get; internal set; }
public int Level { get; internal set; }
public bool Identified { get; internal set; }
public ItemInstance(Item item)
{
Item = item;
}
}
}

View File

@ -9,7 +9,7 @@ namespace OpenDiablo2.Common.Models
{
public sealed class Weapon : Item
{
public string WeaponClass { get; internal set; }
}
public static class WeaponHelper
@ -19,6 +19,7 @@ namespace OpenDiablo2.Common.Models
{
Name = row[0],
Code = row[2],
WeaponClass = row[34],
InvFile = row[45]
};
}

View File

@ -18,10 +18,33 @@ namespace OpenDiablo2.Common.Models
public bool IsTransparent { get; internal set; }
public eDrawEffect DrawEffect { get; internal set; }
public eWeaponClass WeaponClass { get; internal set; }
public string ShieldCode { get; internal set; }
public string WeaponCode { get; internal set; }
// TODO: Move logic somewhere else.
// TODO: Consider two hand weapons.
public string GetDCCPath(eArmorType armorType)
{
var result = $"{ResourcePaths.PlayerAnimationBase}\\{COF.Hero.ToToken()}\\{CompositType.ToToken()}\\{COF.Hero.ToToken()}{CompositType.ToToken()}{armorType.ToToken()}{COF.MobMode.ToToken()}{COF.WeaponClass.ToToken()}.dcc";
string result = null;
var weaponClass = COF.WeaponClass;
if(CompositType != eCompositType.RightArm && CompositType != eCompositType.RightHand)
{
weaponClass = eWeaponClass.HandToHand;
}
if(CompositType == eCompositType.Shield)
{
result = $"{ResourcePaths.PlayerAnimationBase}\\{COF.Hero.ToToken()}\\{CompositType.ToToken()}\\{COF.Hero.ToToken()}{CompositType.ToToken()}{ShieldCode}{COF.MobMode.ToToken()}{weaponClass.ToToken()}.dcc";
}
else if (CompositType == eCompositType.RightHand)
{
result = $"{ResourcePaths.PlayerAnimationBase}\\{COF.Hero.ToToken()}\\{CompositType.ToToken()}\\{COF.Hero.ToToken()}{CompositType.ToToken()}{WeaponCode}{COF.MobMode.ToToken()}{weaponClass.ToToken()}.dcc";
}
else
{
result = $"{ResourcePaths.PlayerAnimationBase}\\{COF.Hero.ToToken()}\\{CompositType.ToToken()}\\{COF.Hero.ToToken()}{CompositType.ToToken()}{armorType.ToToken()}{COF.MobMode.ToToken()}{weaponClass.ToToken()}.dcc";
}
return result;
}
@ -35,7 +58,7 @@ namespace OpenDiablo2.Common.Models
public IEnumerable<COFLayer> Layers { get; private set; }
public IEnumerable<eAnimationFrame> AnimationFrames { get; private set; }
public static MPQCOF Load(Stream stream, Dictionary<string, List<AnimationData>> animations, eHero hero, eWeaponClass weaponClass, eMobMode mobMode)
public static MPQCOF Load(Stream stream, Dictionary<string, List<AnimationData>> animations, eHero hero, eWeaponClass weaponClass, eMobMode mobMode, string ShieldCode, string weaponCode)
{
var result = new MPQCOF
{
@ -66,6 +89,8 @@ namespace OpenDiablo2.Common.Models
layer.DrawEffect = (eDrawEffect)br.ReadByte();
layers.Add(layer);
layer.WeaponClass = Encoding.ASCII.GetString(br.ReadBytes(4)).Trim('\0').ToWeaponClass();
layer.ShieldCode = ShieldCode;
layer.WeaponCode = weaponCode;
}
result.Layers = layers;
result.AnimationFrames = br.ReadBytes(framesPerDir).Select(x => (eAnimationFrame)x);

View File

@ -46,9 +46,7 @@ namespace OpenDiablo2.Common.Models.Mobs
public int StartingSkill { get; protected set; }
public string BaseWeaponClass { get; protected set; }
public IEnumerable<string> ItemNames { get; }
public IEnumerable<string> ItemLocs { get; }
public IEnumerable<int> ItemCounts { get; }
public List<InitialEquipment> InitialEquipment { get; }
public HeroTypeConfig(int vitality, int strength, int dexterity, int energy,
int health, int mana, int stamina, int manaRegen,
@ -59,7 +57,7 @@ namespace OpenDiablo2.Common.Models.Mobs
int walkFrames, int runFrames, int swingFrames, int spellFrames, int getHitFrames, int bowFrames,
int startingSkill,
string baseWeaponClass,
List<string> itemNames, List<string> itemLocs, List<int> itemCounts)
List<InitialEquipment> initialEquipment)
{
StartingDexterity = dexterity;
StartingVitality = vitality;
@ -97,12 +95,17 @@ namespace OpenDiablo2.Common.Models.Mobs
StartingSkill = startingSkill;
BaseWeaponClass = baseWeaponClass;
ItemNames = itemNames;
ItemLocs = itemLocs;
ItemCounts = itemCounts;
InitialEquipment = initialEquipment;
}
}
public struct InitialEquipment
{
public string name;
public string location;
public int count;
};
public static class HeroTypeConfigHelper
{
public static IHeroTypeConfig ToHeroTypeConfig(this string[] row)
@ -134,15 +137,21 @@ namespace OpenDiablo2.Common.Models.Mobs
// 57 58 59 60 61 62
// item9 item9loc item9count item10 item10loc item10count
List<string> itemNames = new List<string>();
List<string> itemLocs = new List<string>();
List<int> itemCounts = new List<int>();
List<InitialEquipment> initialEquipment = new List<InitialEquipment>();
for(int i = 33; i <= 60; i+=3)
{
itemNames.Add(row[i]);
itemLocs.Add(row[i + 1]);
itemCounts.Add(Convert.ToInt32(row[i + 2]));
var item = new InitialEquipment();
item.name = row[i];
item.location = row[i + 1];
item.count = Convert.ToInt32(row[i + 2]);
initialEquipment.Add(item);
}
return new HeroTypeConfig(
@ -175,9 +184,7 @@ namespace OpenDiablo2.Common.Models.Mobs
bowFrames: Convert.ToInt32(row[29]),
startingSkill: Convert.ToInt32(row[31]),
baseWeaponClass: row[32],
itemNames: itemNames,
itemLocs: itemLocs,
itemCounts: itemCounts);
initialEquipment: initialEquipment);
}
}
}

View File

@ -15,6 +15,7 @@
*/
using System;
using System.Collections.Generic;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Enums.Mobs;
using OpenDiablo2.Common.Interfaces.Mobs;
@ -34,6 +35,11 @@ namespace OpenDiablo2.Common.Models.Mobs
public eArmorType ArmorType { get; set; } = eArmorType.Lite; // Temporary
public eMobMode MobMode { get; set; } = eMobMode.PlayerTownWalk; // Temporary
// Remove when we're passing the full inventory. Used for animations.
public string ShieldCode { get; set; }
public string WeaponCode { get; set; }
// ---
// Player character stats
protected Stat Vitality;
protected Stat Strength;
@ -51,7 +57,7 @@ namespace OpenDiablo2.Common.Models.Mobs
protected Stat RunVelocity;
protected Stat RunDrain;
public Dictionary<String, ItemInstance> Equipment = new Dictionary<string, ItemInstance> ();
public long Experience { get; protected set; }
@ -81,6 +87,7 @@ namespace OpenDiablo2.Common.Models.Mobs
Experience = experience; // how much total exp do they have
HeroType = herotype;
HeroTypeConfig = heroconfig;
ExperienceConfig = expconfig;
@ -94,6 +101,27 @@ namespace OpenDiablo2.Common.Models.Mobs
RefreshDerived();
}
public void UpdateEquipment(string slot, ItemInstance item)
{
if(Equipment.ContainsKey(slot))
{
Equipment.Remove(slot);
}
Equipment.Add(slot, item);
if(item.Item is Weapon)
{
WeaponClass = ((Weapon)item.Item).WeaponClass.ToWeaponClass();
WeaponCode = item.Item.Code;
}
if(item.Item is Armor && slot == "larm") // Shield
{
ShieldCode = item.Item.Code;
}
}
#region Level and Experience
public long GetExperienceToLevel()
{

View File

@ -16,6 +16,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Models.Mobs;
@ -31,41 +32,53 @@ namespace OpenDiablo2.Common.Models
public eArmorType ArmorType { get; set; }
public eMobMode MobMode { get; set; }
public PlayerLocationDetails LocationDetails { get; set; }
public string ShieldCode { get; set; }
public string WeaponCode { get; set; }
public byte[] GetBytes()
{
var result = new List<byte>();
var nameBytes = Encoding.UTF8.GetBytes(Name);
result.Add((byte)Hero);
result.Add((byte)WeaponClass);
result.Add((byte)ArmorType);
result.Add((byte)MobMode);
result.AddRange(BitConverter.GetBytes(nameBytes.Length));
result.AddRange(nameBytes);
result.AddRange(LocationDetails.GetBytes());
result.AddRange(UID.ToByteArray());
return result.ToArray();
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream))
{
writer.Write((byte)Hero);
writer.Write((byte)WeaponClass);
writer.Write((byte)ArmorType);
writer.Write((byte)MobMode);
writer.Write(Name);
writer.Write(ShieldCode != null ? ShieldCode : "");
writer.Write(WeaponCode != null ? WeaponCode : "");
writer.Write(LocationDetails.GetBytes());
writer.Write(UID.ToByteArray());
return stream.ToArray();
}
}
public static PlayerInfo FromBytes(byte[] data, int offset = 0)
{
var result = new PlayerInfo
{
Hero = (eHero)data[offset],
WeaponClass = (eWeaponClass)data[offset + 1],
ArmorType = (eArmorType)data[offset + 2],
MobMode = (eMobMode)data[offset + 3]
};
var nameLength = BitConverter.ToInt32(data, offset + 4);
result.Name = Encoding.UTF8.GetString(data, offset + 8, nameLength);
result.LocationDetails = PlayerLocationDetails.FromBytes(data, offset + 8 + nameLength);
var uidBytes = new byte[16];
Array.Copy(data, offset + 8 + nameLength + PlayerLocationDetails.SizeInBytes, uidBytes, 0, 16);
result.UID = new Guid(uidBytes);
return result;
using (var stream = new MemoryStream(data))
using (var reader = new BinaryReader(stream))
{
reader.ReadBytes(offset); // Skip
var result = new PlayerInfo
{
Hero = (eHero)reader.ReadByte(),
WeaponClass = (eWeaponClass)reader.ReadByte(),
ArmorType = (eArmorType)reader.ReadByte(),
MobMode = (eMobMode)reader.ReadByte(),
Name = reader.ReadString(),
ShieldCode = reader.ReadString(),
WeaponCode = reader.ReadString(),
LocationDetails = PlayerLocationDetails.FromBytes(reader.ReadBytes(PlayerLocationDetails.SizeInBytes)),
UID = new Guid(reader.ReadBytes(16))
};
return result;
}
}
public int SizeInBytes => 8 + Encoding.UTF8.GetByteCount(Name) + PlayerLocationDetails.SizeInBytes + 16;
public int SizeInBytes => 8 + Encoding.UTF8.GetByteCount(Name) + PlayerLocationDetails.SizeInBytes + 16;
}
@ -86,7 +99,9 @@ namespace OpenDiablo2.Common.Models
Name = source.Name,
WeaponClass = source.WeaponClass,
ArmorType = source.ArmorType,
MobMode = source.MobMode
MobMode = source.MobMode,
ShieldCode = source.ShieldCode,
WeaponCode = source.WeaponCode
};
}
}

View File

@ -87,6 +87,7 @@
<Compile Include="Exceptions\OpenDiablo2Exception.cs" />
<Compile Include="Extensions\EnumExtensions.cs" />
<Compile Include="Interfaces\Drawing\ICharacterRenderer.cs" />
<Compile Include="Interfaces\IItemInstance.cs" />
<Compile Include="Interfaces\ICache.cs" />
<Compile Include="Interfaces\IItemManager.cs" />
<Compile Include="Extensions\MobManagerExtensions.cs" />
@ -100,6 +101,7 @@
<Compile Include="Interfaces\UI\IPanel.cs" />
<Compile Include="Models\AnimationData.cs" />
<Compile Include="Models\BitMuncher.cs" />
<Compile Include="Models\Item\ItemInstance.cs" />
<Compile Include="Models\MPQCOF.cs" />
<Compile Include="Models\MPQDCC.cs" />
<Compile Include="Models\ItemContainerLayout.cs" />

View File

@ -40,7 +40,7 @@ namespace OpenDiablo2.Core.GameState_
public int Seed { get; internal set; }
public Item SelectedItem { get; internal set; }
public ItemInstance SelectedItem { get; internal set; }
public object ThreadLocker { get; } = new object();
public int CameraOffset { get; set; } = 0;
@ -288,7 +288,7 @@ namespace OpenDiablo2.Core.GameState_
throw new NotImplementedException();
}
public void SelectItem(Item item)
public void SelectItem(ItemInstance item)
{
if (item == null)
{
@ -296,7 +296,7 @@ namespace OpenDiablo2.Core.GameState_
}
else
{
var cursorsprite = renderWindow.LoadSprite(ResourcePaths.GeneratePathForItem(item.InvFile), Palettes.Units);
var cursorsprite = renderWindow.LoadSprite(ResourcePaths.GeneratePathForItem(item.Item.InvFile), Palettes.Units);
renderWindow.MouseCursor = renderWindow.LoadCursor(cursorsprite, 0, new Point(cursorsprite.FrameSize.Width / 2, cursorsprite.FrameSize.Height / 2));
}

View File

@ -36,5 +36,10 @@ namespace OpenDiablo2.Core
return item;
}
public ItemInstance getItemInstance(string code)
{
return new ItemInstance(getItem(code));
}
}
}

View File

@ -92,6 +92,8 @@ namespace OpenDiablo2.Core.Map_Engine
cr.WeaponClass = info.WeaponClass;
cr.Hero = info.Hero;
cr.ArmorType = info.ArmorType;
cr.ShieldCode = info.ShieldCode;
cr.WeaponCode = info.WeaponCode;
characterRenderers.Add(cr);
cr.ResetAnimationData();
}

View File

@ -63,11 +63,11 @@ namespace OpenDiablo2.Core
public MPQDT1 GetMPQDT1(string resourcePath)
=> cache.AddOrGetExisting($"DT1::{resourcePath}", () => new MPQDT1(mpqProvider.GetStream(resourcePath)));
public MPQCOF GetPlayerAnimation(eHero hero, eWeaponClass weaponClass, eMobMode mobMode)
public MPQCOF GetPlayerAnimation(eHero hero, eWeaponClass weaponClass, eMobMode mobMode, string shieldCode, string weaponCode)
=> cache.AddOrGetExisting($"COF::{hero}::{weaponClass}::{mobMode}", () =>
{
var path = $"{ResourcePaths.PlayerAnimationBase}\\{hero.ToToken()}\\COF\\{hero.ToToken()}{mobMode.ToToken()}{weaponClass.ToToken()}.cof";
return MPQCOF.Load(mpqProvider.GetStream(path), Animations, hero, weaponClass, mobMode);
return MPQCOF.Load(mpqProvider.GetStream(path), Animations, hero, weaponClass, mobMode, shieldCode, weaponCode);
});
public MPQDCC GetPlayerDCC(MPQCOF.COFLayer cofLayer, eArmorType armorType, Palette palette)

View File

@ -70,51 +70,39 @@ namespace OpenDiablo2.Core.UI
helmContainer = createItemContainer(eItemContainerType.Helm);
helmContainer.Location = panelSprite.Location + new Size(135, 5);
helmContainer.SetContainedItem(itemManager.getItem("cap"));
amuletContainer = createItemContainer(eItemContainerType.Amulet);
amuletContainer.Location = panelSprite.Location + new Size(209, 34);
amuletContainer.SetContainedItem(itemManager.getItem("vip"));
armorContainer = createItemContainer(eItemContainerType.Armor);
armorContainer.Location = panelSprite.Location + new Size(135, 75);
armorContainer.SetContainedItem(itemManager.getItem("hla"));
leftHandContainer = createItemContainer(eItemContainerType.Weapon);
leftHandContainer.Location = panelSprite.Location + new Size(20, 47);
leftHandContainer.SetContainedItem(itemManager.getItem("ame"));
rightHandContainer = createItemContainer(eItemContainerType.Weapon);
rightHandContainer.Location = panelSprite.Location + new Size(253, 47);
rightHandContainer.SetContainedItem(itemManager.getItem("paf"));
secondaryLeftHandContainer = createItemContainer(eItemContainerType.Weapon);
secondaryLeftHandContainer.Location = panelSprite.Location + new Size(24, 45);
secondaryLeftHandContainer.SetContainedItem(itemManager.getItem("crs"));
secondaryRightHandContainer = createItemContainer(eItemContainerType.Weapon);
secondaryRightHandContainer.Location = panelSprite.Location + new Size(257, 45);
secondaryRightHandContainer.SetContainedItem(itemManager.getItem("kit"));
beltContainer = createItemContainer(eItemContainerType.Belt);
beltContainer.Location = panelSprite.Location + new Size(136, 178);
beltContainer.SetContainedItem(itemManager.getItem("vbl"));
ringtLeftContainer = createItemContainer(eItemContainerType.Ring);
ringtLeftContainer.Location = panelSprite.Location + new Size(95, 179);
ringtLeftContainer.SetContainedItem(itemManager.getItem("rin"));
ringtRightContainer = createItemContainer(eItemContainerType.Ring);
ringtRightContainer.Location = panelSprite.Location + new Size(209, 179);
ringtRightContainer.SetContainedItem(itemManager.getItem("rin"));
gloveContainer = createItemContainer(eItemContainerType.Glove);
gloveContainer.Location = panelSprite.Location + new Size(20, 179);
gloveContainer.SetContainedItem(itemManager.getItem("tgl"));
bootsContainer = createItemContainer(eItemContainerType.Boots);
bootsContainer.Location = panelSprite.Location + new Size(251, 178);
bootsContainer.SetContainedItem(itemManager.getItem("lbt"));
}
public eButtonType PanelType => eButtonType.MinipanelInventory;

View File

@ -17,7 +17,7 @@ namespace OpenDiablo2.Core.UI
private readonly ItemContainerLayout itemContainerLayout;
private readonly IMouseInfoProvider mouseInfoProvider;
public Item ContainedItem { get; internal set; }
public ItemInstance ContainedItem { get; internal set; }
private readonly Dictionary<eItemContainerType, ISprite> sprites = new Dictionary<eItemContainerType, ISprite>();
@ -52,13 +52,13 @@ namespace OpenDiablo2.Core.UI
this.Size = placeholderSprite.FrameSize; // For all but generic size is equal to the placeholder size. Source: me.
}
public void SetContainedItem(Item containedItem)
public void SetContainedItem(ItemInstance containedItem)
{
ContainedItem = containedItem;
if (ContainedItem != null)
{
sprite = renderWindow.LoadSprite(ResourcePaths.GeneratePathForItem(this.ContainedItem.InvFile), Palettes.Units, true);
sprite = renderWindow.LoadSprite(ResourcePaths.GeneratePathForItem(this.ContainedItem.Item.InvFile), Palettes.Units, true);
sprite.Location = new Point(location.X, location.Y + sprite.LocalFrameSize.Height);
}
}
@ -108,7 +108,10 @@ namespace OpenDiablo2.Core.UI
public void Dispose()
{
sprite.Dispose();
if(sprite != null)
{
sprite.Dispose();
}
}
}
}

View File

@ -12,17 +12,19 @@ namespace OpenDiablo2.GameServer_
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private readonly IMobManager mobManager;
private readonly IEngineDataManager engineDataManager;
private readonly IEngineDataManager engineDataManager;
private readonly IItemManager itemManager;
public int Seed { get; private set; }
public IEnumerable<PlayerState> Players => mobManager.Players;
const double Deg2Rad = Math.PI / 180.0;
public GameServer(IMobManager mobManager, IEngineDataManager engineDataManager)
public GameServer(IMobManager mobManager, IEngineDataManager engineDataManager, IItemManager itemManager)
{
this.mobManager = mobManager;
this.engineDataManager = engineDataManager;
this.itemManager = itemManager;
}
public void InitializeNewGame()
@ -53,8 +55,9 @@ namespace OpenDiablo2.GameServer_
else
{
log.Error("Error: Hero Config not loaded for '" + heroType.ToString() + "'.");
heroConfig = new HeroTypeConfig(10, 10, 10, 10, 10, 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 9,
1, 10, 10, 10, 10, 10, 10, 0, "hth", new List<string>(), new List<string>(), new List<int>());
// Do we even need a default?
//heroConfig = new HeroTypeConfig(10, 10, 10, 10, 10, 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 9,
// 1, 10, 10, 10, 10, 10, 10, 0, "hth");
// TODO: should we have a more robust default hero config?
// or should we just fail in some way here?
// ... we should probably just fail here
@ -63,6 +66,17 @@ namespace OpenDiablo2.GameServer_
var newPlayer = new PlayerState(clientHash, playerName, mobManager.GetNextAvailableMobId(), 1, 20.0f, 20.0f, 10, 10, 10, 10, 0, heroType,
heroConfig, expConfig);
// This is probably not the right place to do this.
// Only add items with a location set, the other ones go into the inventory - that we do not support yet
foreach (var item in heroConfig.InitialEquipment)
{
if (item.location.Length > 0)
{
newPlayer.UpdateEquipment(item.location, itemManager.getItemInstance(item.name));
}
}
mobManager.AddPlayer(newPlayer);
return newPlayer.Id;
}

View File

@ -49,6 +49,8 @@ namespace OpenDiablo2.SDL2_
public eWeaponClass WeaponClass { get; set; }
public eArmorType ArmorType { get; set; }
public eMobMode MobMode { get; set; }
public string ShieldCode { get; set; }
public string WeaponCode { get; set; }
private readonly IntPtr renderer;
@ -132,7 +134,7 @@ namespace OpenDiablo2.SDL2_
return;
}
animationData = resourceManager.GetPlayerAnimation(Hero, WeaponClass, MobMode);
animationData = resourceManager.GetPlayerAnimation(Hero, WeaponClass, MobMode, ShieldCode, WeaponCode);
if (animationData == null)
throw new OpenDiablo2Exception("Could not locate animation for the character!");

View File

@ -1,5 +1,8 @@
using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using OpenDiablo2.Common.Attributes;
using OpenDiablo2.Common.Enums;
@ -16,19 +19,25 @@ namespace OpenDiablo2.ServiceBus.Message_Frames.Client
public byte[] Data
{
get => new byte[] { (byte)HeroType }
.Concat(BitConverter.GetBytes((UInt16)PlayerName.Length))
.Concat(Encoding.UTF8.GetBytes(PlayerName))
.ToArray();
get
{
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream)) {
writer.Write((byte)HeroType);
writer.Write(PlayerName);
return stream.ToArray();
}
}
set
{
HeroType = (eHero)value[0];
var playerNameLen = BitConverter.ToUInt16(value, 1);
PlayerName = Encoding.UTF8.GetString(value, 3, value.Length - 3);
if (PlayerName.Length != playerNameLen)
throw new OpenDiablo2Exception("Invalid player length!");
using(var stream = new MemoryStream(value))
using(var reader = new BinaryReader(stream))
{
HeroType = (eHero)reader.ReadByte();
PlayerName = reader.ReadString();
}
}
}