2018-12-05 22:29:45 -05:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using OpenDiablo2.Common.Enums;
|
|
|
|
|
|
|
|
|
|
namespace OpenDiablo2.Common.Models
|
|
|
|
|
{
|
|
|
|
|
public sealed class MPQCOF
|
|
|
|
|
{
|
|
|
|
|
public class COFLayer
|
|
|
|
|
{
|
|
|
|
|
public MPQCOF COF { get; internal set; }
|
|
|
|
|
public eCompositType CompositType { get; internal set; }
|
|
|
|
|
public byte Shadow { get; internal set; }
|
|
|
|
|
public bool IsTransparent { get; internal set; }
|
|
|
|
|
public eDrawEffect DrawEffect { get; internal set; }
|
|
|
|
|
public eWeaponClass WeaponClass { get; internal set; }
|
2018-12-11 00:25:41 -05:00
|
|
|
|
public string ShieldCode { get; internal set; }
|
|
|
|
|
public string WeaponCode { get; internal set; }
|
2018-12-05 22:29:45 -05:00
|
|
|
|
|
2018-12-11 00:25:41 -05:00
|
|
|
|
// TODO: Move logic somewhere else.
|
|
|
|
|
// TODO: Consider two hand weapons.
|
2018-12-05 22:29:45 -05:00
|
|
|
|
public string GetDCCPath(eArmorType armorType)
|
2018-12-07 18:45:54 -05:00
|
|
|
|
{
|
2018-12-11 00:25:41 -05:00
|
|
|
|
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";
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-07 18:45:54 -05:00
|
|
|
|
return result;
|
|
|
|
|
}
|
2018-12-05 22:29:45 -05:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public eHero Hero { get; private set; }
|
|
|
|
|
public eWeaponClass WeaponClass { get; private set; }
|
|
|
|
|
public eMobMode MobMode { get; private set; }
|
|
|
|
|
public List<AnimationData> Animations { get; private set; }
|
|
|
|
|
|
|
|
|
|
public IEnumerable<COFLayer> Layers { get; private set; }
|
|
|
|
|
public IEnumerable<eAnimationFrame> AnimationFrames { get; private set; }
|
2018-12-11 18:15:50 -05:00
|
|
|
|
public byte[] Priority { get; private set; }
|
|
|
|
|
public int NumberOfDirections { get; internal set; }
|
|
|
|
|
public int FramesPerDirection { get; internal set; }
|
|
|
|
|
public int NumberOfLayers { get; internal set; }
|
2018-12-05 22:29:45 -05:00
|
|
|
|
|
2018-12-11 00:25:41 -05:00
|
|
|
|
public static MPQCOF Load(Stream stream, Dictionary<string, List<AnimationData>> animations, eHero hero, eWeaponClass weaponClass, eMobMode mobMode, string ShieldCode, string weaponCode)
|
2018-12-05 22:29:45 -05:00
|
|
|
|
{
|
|
|
|
|
var result = new MPQCOF
|
|
|
|
|
{
|
|
|
|
|
WeaponClass = weaponClass,
|
|
|
|
|
MobMode = mobMode,
|
|
|
|
|
Hero = hero
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var br = new BinaryReader(stream);
|
|
|
|
|
|
2018-12-11 18:15:50 -05:00
|
|
|
|
result.NumberOfLayers = br.ReadByte();
|
|
|
|
|
result.FramesPerDirection = br.ReadByte();
|
|
|
|
|
result.NumberOfDirections = br.ReadByte(); // Number of directions
|
2018-12-05 22:29:45 -05:00
|
|
|
|
|
|
|
|
|
br.ReadBytes(25); // Skip 25 unknown bytes...
|
|
|
|
|
|
|
|
|
|
var layers = new List<COFLayer>();
|
2018-12-11 18:15:50 -05:00
|
|
|
|
for (var layerIdx = 0; layerIdx < result.NumberOfLayers; layerIdx++)
|
2018-12-05 22:29:45 -05:00
|
|
|
|
{
|
2018-12-08 09:32:09 -05:00
|
|
|
|
var layer = new COFLayer
|
|
|
|
|
{
|
|
|
|
|
COF = result,
|
|
|
|
|
CompositType = (eCompositType)br.ReadByte(),
|
|
|
|
|
Shadow = br.ReadByte()
|
|
|
|
|
};
|
2018-12-05 22:29:45 -05:00
|
|
|
|
br.ReadByte(); // Unknown
|
|
|
|
|
layer.IsTransparent = br.ReadByte() != 0;
|
|
|
|
|
layer.DrawEffect = (eDrawEffect)br.ReadByte();
|
|
|
|
|
layers.Add(layer);
|
|
|
|
|
layer.WeaponClass = Encoding.ASCII.GetString(br.ReadBytes(4)).Trim('\0').ToWeaponClass();
|
2018-12-11 00:25:41 -05:00
|
|
|
|
layer.ShieldCode = ShieldCode;
|
|
|
|
|
layer.WeaponCode = weaponCode;
|
2018-12-05 22:29:45 -05:00
|
|
|
|
}
|
|
|
|
|
result.Layers = layers;
|
2018-12-11 18:15:50 -05:00
|
|
|
|
result.AnimationFrames = br.ReadBytes(result.FramesPerDirection).Select(x => (eAnimationFrame)x);
|
|
|
|
|
result.Priority = br.ReadBytes(result.FramesPerDirection * result.NumberOfLayers * result.NumberOfDirections);
|
2018-12-05 22:29:45 -05:00
|
|
|
|
|
|
|
|
|
var cofName = $"{hero.ToToken()}{mobMode.ToToken()}{weaponClass.ToToken()}".ToUpper();
|
|
|
|
|
result.Animations = animations[cofName];
|
|
|
|
|
br.Dispose();
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|