mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-06-20 14:15:23 +00:00
Address Patch MPQ Issue (#52)
* Address patch mpq issue Game can now load patch mpq files and will do so instead of a regular mpq version if a patch version exists. Updated level details & char stats loading * deleted screenshots * merge fixes * Fix weapon.cs Code column moved over one in patch mpq * Fixes: armor/misc/weapon column adjustment and mapgen autofac fix * Fix SelectHeroClass to work with None herotype
This commit is contained in:
parent
8699aad41b
commit
be29a0017e
|
@ -17,9 +17,13 @@ namespace OpenDiablo2.Common.UT
|
|||
energy: 20, health: 50, mana: 40, stamina: 30, manaRegen: 20,
|
||||
perlevelhealth: 3, perlevelmana: 1.5, perlevelstamina: 1,
|
||||
pervitalityhealth: 2, pervitalitystamina: 1, perenergymana: 1.5,
|
||||
perLevelStatPoints: 5,
|
||||
baseatkrating: -30, basedefrating: -30, perdexterityatkrating: 5, perdexteritydefrating: 4,
|
||||
walkVelocity: 6, runVelocity: 9, runDrain: 20, walkFrames: 8, runFrames: 8, swingFrames: 8,
|
||||
spellFrames: 8, getHitFrames: 8, bowFrames: 8, startingSkill: 0, baseWeaponClass: "hth",
|
||||
spellFrames: 8, getHitFrames: 8, bowFrames: 8, startingSkill: "",
|
||||
startingSkills: new string[] { },
|
||||
allSkillsBonusString: "", firstTabBonusString: "", secondTabBonusString: "",
|
||||
thirdTabBonusString: "", classOnlyBonusString: "", baseWeaponClass: "hth",
|
||||
initialEquipment: new List<InitialEquipment>());
|
||||
LevelExperienceConfig expconfig = new LevelExperienceConfig(new List<long>()
|
||||
{
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
namespace OpenDiablo2.Common.Enums
|
||||
{
|
||||
public enum eButtonType
|
||||
{
|
||||
Wide,
|
||||
Medium,
|
||||
Narrow,
|
||||
Cancel,
|
||||
Tall,
|
||||
Short,
|
||||
// Game UI
|
||||
Skill,
|
||||
Run,
|
||||
Menu,
|
||||
GoldCoin,
|
||||
Close,
|
||||
SecondaryInvHand,
|
||||
MinipanelCharacter,
|
||||
MinipanelInventory,
|
||||
MinipanelSkill,
|
||||
MinipanelAutomap,
|
||||
MinipanelMessage,
|
||||
MinipanelQuest,
|
||||
MinipanelMenu
|
||||
}
|
||||
}
|
||||
namespace OpenDiablo2.Common.Enums
|
||||
{
|
||||
public enum eButtonType
|
||||
{
|
||||
Wide,
|
||||
Medium,
|
||||
Narrow,
|
||||
Cancel,
|
||||
Tall,
|
||||
Short,
|
||||
// Game UI
|
||||
Skill,
|
||||
Run,
|
||||
Menu,
|
||||
GoldCoin,
|
||||
Close,
|
||||
SecondaryInvHand,
|
||||
MinipanelCharacter,
|
||||
MinipanelInventory,
|
||||
MinipanelSkill,
|
||||
MinipanelAutomap,
|
||||
MinipanelMessage,
|
||||
MinipanelQuest,
|
||||
MinipanelMenu
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,13 +15,14 @@ namespace OpenDiablo2.Common.Interfaces
|
|||
string MapName { get; }
|
||||
Palette CurrentPalette { get; }
|
||||
IEnumerable<PlayerInfo> PlayerInfos { get; }
|
||||
eDifficulty Difficulty { get; }
|
||||
|
||||
ItemInstance SelectedItem { get; }
|
||||
void SelectItem(ItemInstance item);
|
||||
|
||||
int CameraOffset { get; set; }
|
||||
|
||||
void Initialize(string characterName, eHero hero, eSessionType sessionType);
|
||||
void Initialize(string characterName, eHero hero, eSessionType sessionType, eDifficulty difficulty);
|
||||
void Update(long ms);
|
||||
IEnumerable<MapCellInfo> GetMapCellInfo(int cellX, int cellY, eRenderCellType renderCellType);
|
||||
void UpdateMapCellInfo(int cellX, int cellY, eRenderCellType renderCellType, IEnumerable<MapCellInfo> mapCellInfo);
|
||||
|
|
|
@ -28,6 +28,8 @@ namespace OpenDiablo2.Common.Interfaces.Mobs
|
|||
double PerVitalityStamina { get; }
|
||||
double PerEnergyMana { get; }
|
||||
|
||||
int PerLevelStatPoints { get; }
|
||||
|
||||
int BaseAttackRating { get; }
|
||||
int PerDexterityAttackRating { get; }
|
||||
|
||||
|
@ -45,7 +47,14 @@ namespace OpenDiablo2.Common.Interfaces.Mobs
|
|||
int GetHitFrames { get; }
|
||||
int BowFrames { get; }
|
||||
|
||||
int StartingSkill { get; }
|
||||
string StartingSkill { get; }
|
||||
string[] StartingSkills { get; }
|
||||
|
||||
string AllSkillsBonusString { get; }
|
||||
string FirstTabBonusString { get; }
|
||||
string SecondTabBonusString { get; }
|
||||
string ThirdTabBonusString { get; }
|
||||
string ClassOnlyBonusString { get; }
|
||||
string BaseWeaponClass { get; }
|
||||
|
||||
List<InitialEquipment> InitialEquipment { get; }
|
||||
|
|
12
OpenDiablo2.Common/Interfaces/Mobs/IMissileTypeConfig.cs
Normal file
12
OpenDiablo2.Common/Interfaces/Mobs/IMissileTypeConfig.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OpenDiablo2.Common.Interfaces.Mobs
|
||||
{
|
||||
public interface IMissileTypeConfig
|
||||
{
|
||||
}
|
||||
}
|
|
@ -1,66 +1,66 @@
|
|||
/* 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.Enums;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenDiablo2.Common.Models
|
||||
{
|
||||
public class ButtonLayout
|
||||
{
|
||||
public int XSegments { get; set; } = 1;
|
||||
public int YSegments { get; set; } = 1;
|
||||
public string ResourceName { get; set; }
|
||||
public string PaletteName { get; set; }
|
||||
public bool Toggleable { get; set; } = false;
|
||||
public int BaseFrame { get; set; } = 0;
|
||||
public int DisabledFrame { get; set; } = -1;
|
||||
public string FontPath { get; set; } = ResourcePaths.FontExocet10;
|
||||
public Rectangle ClickableRect { get; set; }
|
||||
public bool AllowFrameChange { get; set; } = true;
|
||||
|
||||
public bool IsDarkenedWhenDisabled => DisabledFrame == -1;
|
||||
|
||||
public static ImmutableDictionary<eButtonType, ButtonLayout> Values { get; } = new Dictionary<eButtonType, ButtonLayout>
|
||||
{
|
||||
{eButtonType.Wide, new ButtonLayout { XSegments = 2, ResourceName = ResourcePaths.WideButtonBlank, PaletteName = Palettes.Units } },
|
||||
{eButtonType.Medium, new ButtonLayout{ ResourceName = ResourcePaths.MediumButtonBlank, PaletteName = Palettes.Units } },
|
||||
{eButtonType.Narrow, new ButtonLayout { ResourceName = ResourcePaths.NarrowButtonBlank, PaletteName = Palettes.Units } },
|
||||
{eButtonType.Tall, new ButtonLayout { ResourceName = ResourcePaths.TallButtonBlank, PaletteName = Palettes.Units } },
|
||||
{eButtonType.Short, new ButtonLayout { ResourceName = ResourcePaths.ShortButtonBlank, PaletteName = Palettes.Units, FontPath = ResourcePaths.FontExocet10 } },
|
||||
{eButtonType.Cancel, new ButtonLayout { ResourceName = ResourcePaths.CancelButton, PaletteName = Palettes.Units } },
|
||||
// Minipanel
|
||||
{eButtonType.MinipanelCharacter, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 0 } },
|
||||
{eButtonType.MinipanelInventory, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 2 } },
|
||||
{eButtonType.MinipanelSkill, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 4 } },
|
||||
{eButtonType.MinipanelAutomap, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 8 } },
|
||||
{eButtonType.MinipanelMessage, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 10 } },
|
||||
{eButtonType.MinipanelQuest, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 12 } },
|
||||
{eButtonType.MinipanelMenu, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 14 } },
|
||||
|
||||
{eButtonType.SecondaryInvHand, new ButtonLayout { ResourceName = ResourcePaths.InventoryWeaponsTab, PaletteName = Palettes.Units,
|
||||
ClickableRect = new Rectangle(0, 0, 0, 20), AllowFrameChange = false } },
|
||||
{eButtonType.Run, new ButtonLayout { ResourceName = ResourcePaths.RunButton, PaletteName = Palettes.Units, Toggleable = true } },
|
||||
{eButtonType.Menu, new ButtonLayout { ResourceName = ResourcePaths.MenuButton, PaletteName = Palettes.Units, Toggleable = true } },
|
||||
{eButtonType.GoldCoin, new ButtonLayout { ResourceName = ResourcePaths.GoldCoinButton, PaletteName = Palettes.Units } },
|
||||
{eButtonType.Close, new ButtonLayout { ResourceName = ResourcePaths.SquareButton, PaletteName = Palettes.Units, BaseFrame = 10 } },
|
||||
{eButtonType.Skill, new ButtonLayout { ResourceName = ResourcePaths.AddSkillButton, PaletteName = Palettes.Units, DisabledFrame = 2 } },
|
||||
}.ToImmutableDictionary();
|
||||
}
|
||||
|
||||
}
|
||||
/* 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.Enums;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenDiablo2.Common.Models
|
||||
{
|
||||
public class ButtonLayout
|
||||
{
|
||||
public int XSegments { get; set; } = 1;
|
||||
public int YSegments { get; set; } = 1;
|
||||
public string ResourceName { get; set; }
|
||||
public string PaletteName { get; set; }
|
||||
public bool Toggleable { get; set; } = false;
|
||||
public int BaseFrame { get; set; } = 0;
|
||||
public int DisabledFrame { get; set; } = -1;
|
||||
public string FontPath { get; set; } = ResourcePaths.FontExocet10;
|
||||
public Rectangle ClickableRect { get; set; }
|
||||
public bool AllowFrameChange { get; set; } = true;
|
||||
|
||||
public bool IsDarkenedWhenDisabled => DisabledFrame == -1;
|
||||
|
||||
public static ImmutableDictionary<eButtonType, ButtonLayout> Values { get; } = new Dictionary<eButtonType, ButtonLayout>
|
||||
{
|
||||
{eButtonType.Wide, new ButtonLayout { XSegments = 2, ResourceName = ResourcePaths.WideButtonBlank, PaletteName = Palettes.Units } },
|
||||
{eButtonType.Medium, new ButtonLayout{ ResourceName = ResourcePaths.MediumButtonBlank, PaletteName = Palettes.Units } },
|
||||
{eButtonType.Narrow, new ButtonLayout { ResourceName = ResourcePaths.NarrowButtonBlank, PaletteName = Palettes.Units } },
|
||||
{eButtonType.Tall, new ButtonLayout { ResourceName = ResourcePaths.TallButtonBlank, PaletteName = Palettes.Units } },
|
||||
{eButtonType.Short, new ButtonLayout { ResourceName = ResourcePaths.ShortButtonBlank, PaletteName = Palettes.Units, FontPath = ResourcePaths.FontExocet10 } },
|
||||
{eButtonType.Cancel, new ButtonLayout { ResourceName = ResourcePaths.CancelButton, PaletteName = Palettes.Units } },
|
||||
// Minipanel
|
||||
{eButtonType.MinipanelCharacter, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 0 } },
|
||||
{eButtonType.MinipanelInventory, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 2 } },
|
||||
{eButtonType.MinipanelSkill, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 4 } },
|
||||
{eButtonType.MinipanelAutomap, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 8 } },
|
||||
{eButtonType.MinipanelMessage, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 10 } },
|
||||
{eButtonType.MinipanelQuest, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 12 } },
|
||||
{eButtonType.MinipanelMenu, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 14 } },
|
||||
|
||||
{eButtonType.SecondaryInvHand, new ButtonLayout { ResourceName = ResourcePaths.InventoryWeaponsTab, PaletteName = Palettes.Units,
|
||||
ClickableRect = new Rectangle(0, 0, 0, 20), AllowFrameChange = false } },
|
||||
{eButtonType.Run, new ButtonLayout { ResourceName = ResourcePaths.RunButton, PaletteName = Palettes.Units, Toggleable = true } },
|
||||
{eButtonType.Menu, new ButtonLayout { ResourceName = ResourcePaths.MenuButton, PaletteName = Palettes.Units, Toggleable = true } },
|
||||
{eButtonType.GoldCoin, new ButtonLayout { ResourceName = ResourcePaths.GoldCoinButton, PaletteName = Palettes.Units } },
|
||||
{eButtonType.Close, new ButtonLayout { ResourceName = ResourcePaths.SquareButton, PaletteName = Palettes.Units, BaseFrame = 10 } },
|
||||
{eButtonType.Skill, new ButtonLayout { ResourceName = ResourcePaths.AddSkillButton, PaletteName = Palettes.Units, DisabledFrame = 2 } },
|
||||
}.ToImmutableDictionary();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace OpenDiablo2.Common.Models
|
|||
{
|
||||
Name = row[0],
|
||||
Code = row[17],
|
||||
InvFile = row[33]
|
||||
InvFile = row[34]
|
||||
};
|
||||
|
||||
public static void Write(this BinaryWriter binaryWriter, Armor armor)
|
||||
|
|
|
@ -19,8 +19,8 @@ namespace OpenDiablo2.Common.Models
|
|||
=> new Misc
|
||||
{
|
||||
Name = row[0],
|
||||
Code = row[12],
|
||||
InvFile = row[21]
|
||||
Code = row[13],
|
||||
InvFile = row[23]
|
||||
};
|
||||
|
||||
public static void Write(this BinaryWriter binaryWriter, Misc misc)
|
||||
|
|
|
@ -19,9 +19,9 @@ namespace OpenDiablo2.Common.Models
|
|||
=> new Weapon
|
||||
{
|
||||
Name = row[0],
|
||||
Code = row[2],
|
||||
WeaponClass = row[34],
|
||||
InvFile = row[45]
|
||||
Code = row[3],
|
||||
WeaponClass = row[37],
|
||||
InvFile = row[48]
|
||||
};
|
||||
|
||||
public static void Write(this BinaryWriter binaryWriter, Weapon weapon)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
@ -6,6 +7,31 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace OpenDiablo2.Common.Models
|
||||
{
|
||||
public sealed class LevelDetailDifficulty
|
||||
{
|
||||
/// <summary>Horizontal size of the level</summary>
|
||||
public int SizeX { get; internal set; }
|
||||
/// <summary>Vertical size of the level</summary>
|
||||
public int SizeY { get; internal set; }
|
||||
|
||||
/// <summary>Level (controls the item level of items that drop from chests etc)</summary>
|
||||
public int MonLevel { get; internal set; }
|
||||
/// <summary> MonLevel, but for expansion games (only use if non-null) </summary>
|
||||
public int? MonLevelEx { get; internal set; }
|
||||
|
||||
/// <summary>The Density of Monsters</summary>
|
||||
public int MonDen { get; internal set; }
|
||||
|
||||
/// <summary>Minimum Unique and Champion Monsters Spawned in this Level</summary>
|
||||
public int MonUMin { get; internal set; }
|
||||
|
||||
/// <summary>Maximum Unique and Champion Monsters Spawned in this Level</summary>
|
||||
public int MonUMax { get; internal set; }
|
||||
|
||||
/// <summary>Monster Species 1-25 (use ID from MonStats.txt)</summary>
|
||||
public string[] M1_25 { get; internal set; }
|
||||
}
|
||||
|
||||
public sealed class LevelDetail
|
||||
{
|
||||
/// <summary>Internal level name</summary>
|
||||
|
@ -14,20 +40,26 @@ namespace OpenDiablo2.Common.Models
|
|||
/// <summary>Level ID (Used in columns like VIS0-1)</summary>
|
||||
public int Id { get; internal set; }
|
||||
|
||||
public Dictionary<eDifficulty, LevelDetailDifficulty> Difficulties = new Dictionary<eDifficulty, LevelDetailDifficulty>();
|
||||
|
||||
/// <summary>Palette</summary>
|
||||
public int Pal { get; internal set; }
|
||||
|
||||
/// <summary>Act</summary>
|
||||
public int Act { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used in classic (non-expansion) games
|
||||
/// If this is set, the character must have completed the quest with this id to take a portal here
|
||||
/// </summary>
|
||||
public int? QuestFlag { get; internal set; }
|
||||
/// <summary> See above, but for expansion games </summary>
|
||||
public int? QuestFlagEx { get; internal set; }
|
||||
|
||||
/// <summary>What layer the level is on (surface levels are always 0)</summary>
|
||||
public int Layer { get; internal set; }
|
||||
|
||||
/// <summary>Horizontal size of the level</summary>
|
||||
public int SizeX { get; internal set; }
|
||||
|
||||
/// <summary>Vertical size of the level</summary>
|
||||
public int SizeY { get; internal set; }
|
||||
|
||||
|
||||
/// <summary>Horizontal Placement Offset</summary>
|
||||
public int OffsetX { get; internal set; }
|
||||
|
@ -38,29 +70,34 @@ namespace OpenDiablo2.Common.Models
|
|||
/// <summary>Special setting for levels that aren't random or preset (like Outer Cloister and Arcane Sancturary)</summary>
|
||||
public int Depend { get; internal set; }
|
||||
|
||||
/// <summary> if false, teleport not allowed in this level </summary>
|
||||
public bool Teleport { get; internal set; }
|
||||
/// <summary> if true, cannot teleport through walls and objects in this level </summary>
|
||||
public bool CantTeleportThroughWallsObjects { get; internal set; }
|
||||
|
||||
/// <summary>If true, it rains (or snows)</summary>
|
||||
public int Rain { get; internal set; }
|
||||
public bool Rain { get; internal set; }
|
||||
|
||||
/// <summary>Unused</summary>
|
||||
public int Mud { get; internal set; }
|
||||
public bool Mud { get; internal set; }
|
||||
|
||||
/// <summary>Perspective mode forced to off if set to 1</summary>
|
||||
public int NoPer { get; internal set; }
|
||||
public bool NoPer { get; internal set; }
|
||||
|
||||
/// <summary>Level of sight drawing</summary>
|
||||
public int LOSDraw { get; internal set; }
|
||||
public bool LOSDraw { get; internal set; }
|
||||
|
||||
/// <summary>Unknown</summary>
|
||||
public int FloorFilter { get; internal set; }
|
||||
public bool FloorFilter { get; internal set; }
|
||||
|
||||
/// <summary>Unknown</summary>
|
||||
public int BlankScreen { get; internal set; }
|
||||
public bool BlankScreen { get; internal set; }
|
||||
|
||||
/// <summary>For levels bordered with mountains or walls</summary>
|
||||
public int DrawEdges { get; internal set; }
|
||||
public bool DrawEdges { get; internal set; }
|
||||
|
||||
/// <summary>Set to 1 if this is underground or inside</summary>
|
||||
public int IsInside { get; internal set; }
|
||||
public bool IsInside { get; internal set; }
|
||||
|
||||
/// <summary> Setting for Level Generation: 1=Random Size, amount of rooms defined by LVLMAZE.TXT, 2=pre set map (example: catacombs lvl4) and 3=Random Area with preset size (wildernesses)</summary>
|
||||
public int DrlgType { get; internal set; }
|
||||
|
@ -99,13 +136,13 @@ namespace OpenDiablo2.Common.Models
|
|||
public int Blue { get; internal set; }
|
||||
|
||||
/// <summary>Unknown</summary>
|
||||
public int Portal { get; internal set; }
|
||||
public bool Portal { get; internal set; }
|
||||
|
||||
/// <summary>Settings for preset levels</summary>
|
||||
public int Position { get; internal set; }
|
||||
public bool Position { get; internal set; }
|
||||
|
||||
/// <summary>If true, monster/creatures get saved/loaded instead of despawning.</summary>
|
||||
public int SaveMonsters { get; internal set; }
|
||||
public bool SaveMonsters { get; internal set; }
|
||||
|
||||
/// <summary>Quest flags</summary>
|
||||
public int Quest { get; internal set; }
|
||||
|
@ -113,23 +150,9 @@ namespace OpenDiablo2.Common.Models
|
|||
/// <summary>Usually 2025, unknown</summary>
|
||||
public int WarpDist { get; internal set; }
|
||||
|
||||
/// <summary>Level on Normal (controls the item level of items that drop from chests etc)</summary>
|
||||
public int MonLvl1 { get; internal set; }
|
||||
|
||||
|
||||
/// <summary>Level on Nightmare (controls the item level of items that drop from chests etc)</summary>
|
||||
public int MonLvl2 { get; internal set; }
|
||||
|
||||
/// <summary> Level on Hell (controls the item level of items that drop from chests etc)</summary>
|
||||
public int MonLvl3 { get; internal set; }
|
||||
|
||||
/// <summary>The Density of Monsters</summary>
|
||||
public int MonDen { get; internal set; }
|
||||
|
||||
/// <summary>Minimum Unique and Champion Monsters Spawned in this Level</summary>
|
||||
public int MonUMin { get; internal set; }
|
||||
|
||||
/// <summary>Maximum Unique and Champion Monsters Spawned in this Level</summary>
|
||||
public int MonUMax { get; internal set; }
|
||||
|
||||
|
||||
/// <summary></summary>
|
||||
public int MonWndr { get; internal set; }
|
||||
|
@ -140,26 +163,20 @@ namespace OpenDiablo2.Common.Models
|
|||
/// <summary>How many different Species of Monsters can occur in this area (example: if you use M1-25 then set Mtot to 25 etc)</summary>
|
||||
public int Mtot { get; internal set; }
|
||||
|
||||
/// <summary>Monster Species 1-25 (use ID from MonStats.txt)</summary>
|
||||
public int[] M1_25 { get; internal set; }
|
||||
|
||||
/// <summary>Spawned Species 1-25 (use ID from MonStats for Monsters which have eSpawnCol set to 2, related to M1-25, eg: if M1 Spawns S1 will Spawn)</summary>
|
||||
public int[] S1_25 { get; internal set; }
|
||||
|
||||
/// <summary>How many different Species of Monsters can spawn as Uniques and Champions in this Area (works like Mtot)</summary>
|
||||
public int Utot { get; internal set; }
|
||||
/// <summary> If true, ranged monsters have spawning preference </summary>
|
||||
public bool RangedSpawnPreference { get; internal set; }
|
||||
|
||||
/// <summary> Unique Species 1-25 (same as M1-M25 just for Monsters that you want to appear as Unique/Champions)</summary>
|
||||
public int[] U1_25 { get; internal set; }
|
||||
public string[] U1_25 { get; internal set; }
|
||||
|
||||
/// <summary>Critter Species 1-5 (For monsters set to 1 in the IsCritter Column in MonStats.txt)</summary>
|
||||
public int[] C1_5 { get; internal set; }
|
||||
/// <summary>Critter Species 1-4 (For monsters set to 1 in the IsCritter Column in MonStats.txt)</summary>
|
||||
public string[] C1_4 { get; internal set; }
|
||||
|
||||
/// <summary>Related to C1-5, eg: if you spawn a critter thru C1 then set this column to 30 etc. (function unknown)</summary>
|
||||
public int[] CA1_5 { get; internal set; }
|
||||
/// <summary>Related to C1-5, eg: if you spawn a critter thru C1 then set this column to 30 etc. Controls chance for critter to spawn.</summary>
|
||||
public int[] CA1_4 { get; internal set; }
|
||||
|
||||
/// <summary>Unknown</summary>
|
||||
public int[] CD1_5 { get; internal set; }
|
||||
/// <summary>Unknown and unused</summary>
|
||||
public int[] CD1_4 { get; internal set; }
|
||||
|
||||
/// <summary>unknown</summary>
|
||||
public int Themes { get; internal set; }
|
||||
|
@ -195,28 +212,60 @@ namespace OpenDiablo2.Common.Models
|
|||
|
||||
public static class LevelDetailHelper
|
||||
{
|
||||
private static int? IntOrEmpty(string s)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(s))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Convert.ToInt32(s);
|
||||
}
|
||||
|
||||
private static int IntOrZero(string s)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(s))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Convert.ToInt32(s);
|
||||
}
|
||||
|
||||
public static LevelDetail ToLevelDetail(this string[] v, IEnumerable<LevelPreset> levelPresets, IEnumerable<LevelType> levelTypes)
|
||||
{
|
||||
var result = new LevelDetail();
|
||||
result.Difficulties.Add(eDifficulty.NORMAL, new LevelDetailDifficulty());
|
||||
result.Difficulties.Add(eDifficulty.NIGHTMARE, new LevelDetailDifficulty());
|
||||
result.Difficulties.Add(eDifficulty.HELL, new LevelDetailDifficulty());
|
||||
int i = 0;
|
||||
result.Name = v[i++];
|
||||
result.Id = Convert.ToInt32(v[i++]);
|
||||
result.Pal = Convert.ToInt32(v[i++]);
|
||||
result.Act = Convert.ToInt32(v[i++]);
|
||||
result.QuestFlag = IntOrEmpty(v[i++]);
|
||||
result.QuestFlagEx = IntOrEmpty(v[i++]);
|
||||
result.Layer = Convert.ToInt32(v[i++]);
|
||||
result.SizeX = Convert.ToInt32(v[i++]);
|
||||
result.SizeY = Convert.ToInt32(v[i++]);
|
||||
result.Difficulties[eDifficulty.NORMAL].SizeX = Convert.ToInt32(v[i++]);
|
||||
result.Difficulties[eDifficulty.NORMAL].SizeY = Convert.ToInt32(v[i++]);
|
||||
result.Difficulties[eDifficulty.NIGHTMARE].SizeX = Convert.ToInt32(v[i++]);
|
||||
result.Difficulties[eDifficulty.NIGHTMARE].SizeY = Convert.ToInt32(v[i++]);
|
||||
result.Difficulties[eDifficulty.HELL].SizeX = Convert.ToInt32(v[i++]);
|
||||
result.Difficulties[eDifficulty.HELL].SizeY = Convert.ToInt32(v[i++]);
|
||||
result.OffsetX = Convert.ToInt32(v[i++]);
|
||||
result.OffsetY = Convert.ToInt32(v[i++]);
|
||||
result.Depend = Convert.ToInt32(v[i++]);
|
||||
result.Rain = Convert.ToInt32(v[i++]);
|
||||
result.Mud = Convert.ToInt32(v[i++]);
|
||||
result.NoPer = Convert.ToInt32(v[i++]);
|
||||
result.LOSDraw = Convert.ToInt32(v[i++]);
|
||||
result.FloorFilter = Convert.ToInt32(v[i++]);
|
||||
result.BlankScreen = Convert.ToInt32(v[i++]);
|
||||
result.DrawEdges = Convert.ToInt32(v[i++]);
|
||||
result.IsInside = Convert.ToInt32(v[i++]);
|
||||
result.Teleport = (v[i] == "1" || v[i] == "2");
|
||||
result.CantTeleportThroughWallsObjects = (v[i] == "0" || v[i] == "2");
|
||||
i++;
|
||||
result.Rain = (v[i++] == "1");
|
||||
result.Mud = (v[i++] == "1");
|
||||
result.NoPer = (v[i++] == "1");
|
||||
result.LOSDraw = (v[i++] == "1");
|
||||
result.FloorFilter = (v[i++] == "1");
|
||||
result.BlankScreen = (v[i++] == "1");
|
||||
result.DrawEdges = (v[i++] == "1");
|
||||
result.IsInside = (v[i++] == "1");
|
||||
result.DrlgType = Convert.ToInt32(v[i++]);
|
||||
result.LevelTypeId = Convert.ToInt32(v[i++]);
|
||||
result.SubType = Convert.ToInt32(v[i++]);
|
||||
|
@ -231,33 +280,52 @@ namespace OpenDiablo2.Common.Models
|
|||
result.Red = Convert.ToInt32(v[i++]);
|
||||
result.Green = Convert.ToInt32(v[i++]);
|
||||
result.Blue = Convert.ToInt32(v[i++]);
|
||||
result.Portal = Convert.ToInt32(v[i++]);
|
||||
result.Position = Convert.ToInt32(v[i++]);
|
||||
result.SaveMonsters = Convert.ToInt32(v[i++]);
|
||||
result.Portal = (v[i++] == "1");
|
||||
result.Position = (v[i++] == "1");
|
||||
result.SaveMonsters = (v[i++] == "1");
|
||||
result.Quest = Convert.ToInt32(v[i++]);
|
||||
result.WarpDist = Convert.ToInt32(v[i++]);
|
||||
result.MonLvl1 = Convert.ToInt32(v[i++]);
|
||||
result.MonLvl2 = Convert.ToInt32(v[i++]);
|
||||
result.MonLvl3 = Convert.ToInt32(v[i++]);
|
||||
result.MonDen = Convert.ToInt32(v[i++]);
|
||||
result.MonUMin = Convert.ToInt32(v[i++]);
|
||||
result.MonUMax = Convert.ToInt32(v[i++]);
|
||||
result.Difficulties[eDifficulty.NORMAL].MonLevel = Convert.ToInt32(v[i++]);
|
||||
result.Difficulties[eDifficulty.NIGHTMARE].MonLevel = Convert.ToInt32(v[i++]);
|
||||
result.Difficulties[eDifficulty.HELL].MonLevel = Convert.ToInt32(v[i++]);
|
||||
result.Difficulties[eDifficulty.NORMAL].MonLevelEx = IntOrEmpty(v[i++]);
|
||||
result.Difficulties[eDifficulty.NIGHTMARE].MonLevelEx = IntOrEmpty(v[i++]);
|
||||
result.Difficulties[eDifficulty.HELL].MonLevelEx = IntOrEmpty(v[i++]);
|
||||
result.Difficulties[eDifficulty.NORMAL].MonDen = Convert.ToInt32(v[i++]);
|
||||
result.Difficulties[eDifficulty.NIGHTMARE].MonDen = Convert.ToInt32(v[i++]);
|
||||
result.Difficulties[eDifficulty.HELL].MonDen = Convert.ToInt32(v[i++]);
|
||||
result.Difficulties[eDifficulty.NORMAL].MonUMin = IntOrZero(v[i++]);
|
||||
result.Difficulties[eDifficulty.NORMAL].MonUMax = IntOrZero(v[i++]);
|
||||
result.Difficulties[eDifficulty.NIGHTMARE].MonUMin = IntOrZero(v[i++]);
|
||||
result.Difficulties[eDifficulty.NIGHTMARE].MonUMax = IntOrZero(v[i++]);
|
||||
result.Difficulties[eDifficulty.HELL].MonUMin = IntOrZero(v[i++]);
|
||||
result.Difficulties[eDifficulty.HELL].MonUMax = IntOrZero(v[i++]);
|
||||
result.MonWndr = Convert.ToInt32(v[i++]);
|
||||
result.MonSpcWalk = Convert.ToInt32(v[i++]);
|
||||
result.Mtot = Convert.ToInt32(v[i++]);
|
||||
result.M1_25 = new int[25];
|
||||
for (int j = 0; j < 25; j++) result.M1_25[j] = Convert.ToInt32(v[i++]);
|
||||
result.S1_25 = new int[25];
|
||||
for (int j = 0; j < 25; j++) result.S1_25[j] = Convert.ToInt32(v[i++]);
|
||||
result.Utot = Convert.ToInt32(v[i++]);
|
||||
result.U1_25 = new int[25];
|
||||
for (int j = 0; j < 25; j++) result.U1_25[j] = Convert.ToInt32(v[i++]);
|
||||
result.C1_5 = new int[5];
|
||||
for (int j = 0; j < 5; j++) result.C1_5[j] = Convert.ToInt32(v[i++]);
|
||||
result.CA1_5 = new int[5];
|
||||
for (int j = 0; j < 5; j++) result.CA1_5[j] = Convert.ToInt32(v[i++]);
|
||||
result.CD1_5 = new int[5];
|
||||
for (int j = 0; j < 5; j++) result.CD1_5[j] = Convert.ToInt32(v[i++]);
|
||||
result.Mtot = IntOrZero(v[i++]);
|
||||
result.Difficulties[eDifficulty.NORMAL].M1_25 = new string[25]; // NOTE: the game will accept up to 25,
|
||||
// but only the first 10 are present in the mpq provided table
|
||||
// TODO: add check to see if the other 11-25 are present instead of only taking the first 10
|
||||
for (int j = 0; j < 10; j++) result.Difficulties[eDifficulty.NORMAL].M1_25[j] = v[i++];
|
||||
|
||||
result.RangedSpawnPreference = (v[i++] == "1");
|
||||
result.Difficulties[eDifficulty.NIGHTMARE].M1_25 = new string[25];
|
||||
result.Difficulties[eDifficulty.HELL].M1_25 = new string[25];
|
||||
// See above TODO
|
||||
for (int j = 0; j < 10; j++)
|
||||
{
|
||||
result.Difficulties[eDifficulty.NIGHTMARE].M1_25[j] = v[i]; // note: currently these are the same
|
||||
result.Difficulties[eDifficulty.HELL].M1_25[j] = v[i++];
|
||||
}
|
||||
result.U1_25 = new string[25];
|
||||
// See above TODO
|
||||
for (int j = 0; j < 10; j++) result.U1_25[j] = v[i++];
|
||||
result.C1_4 = new string[4];
|
||||
for (int j = 0; j < 4; j++) result.C1_4[j] = v[i++];
|
||||
result.CA1_4 = new int[4];
|
||||
for (int j = 0; j < 4; j++) result.CA1_4[j] = IntOrZero(v[i++]);
|
||||
result.CD1_4 = new int[4];
|
||||
for (int j = 0; j < 4; j++) result.CD1_4[j] = IntOrZero(v[i++]);
|
||||
result.Themes = Convert.ToInt32(v[i++]);
|
||||
result.SoundEnv = Convert.ToInt32(v[i++]);
|
||||
result.Waypoint = Convert.ToInt32(v[i++]);
|
||||
|
|
|
@ -53,7 +53,9 @@ namespace OpenDiablo2.Common.Models
|
|||
KeyAdjusted = 0x00020000, // The file's encryption key is adjusted by the block offset and file size (explained in detail in the File Data section). File must be encrypted.
|
||||
IsEncrypted = 0x00010000, // File is encrypted.
|
||||
IsCompressed = 0x00000200, // File is compressed. File cannot be imploded.
|
||||
IsImploded = 0x00000100 // File is imploded. File cannot be compressed.
|
||||
IsImploded = 0x00000100, // File is imploded. File cannot be compressed.
|
||||
IsPatchFile = 0x00100000, // Marks as a mpq patch file
|
||||
IsDeleteFile = 0x02000000, // Marks as a delete request
|
||||
}
|
||||
|
||||
internal struct BlockRecord
|
||||
|
@ -71,6 +73,8 @@ namespace OpenDiablo2.Common.Models
|
|||
public bool IsEncrypted => (Flags & (UInt32)eBlockRecordBitflag.IsEncrypted) != 0;
|
||||
public bool IsCompressed => (Flags & (UInt32)eBlockRecordBitflag.IsCompressed) != 0;
|
||||
public bool IsImploded => (Flags & (UInt32)eBlockRecordBitflag.IsImploded) != 0;
|
||||
public bool IsPatchFile => (Flags & (UInt32)eBlockRecordBitflag.IsPatchFile) != 0;
|
||||
public bool IsDeleteFile => (Flags & (UInt32)eBlockRecordBitflag.IsDeleteFile) != 0;
|
||||
}
|
||||
|
||||
internal struct HashRecord
|
||||
|
@ -94,9 +98,15 @@ namespace OpenDiablo2.Common.Models
|
|||
public string Path { get; private set; }
|
||||
public eMPQFormatVersion FormatVersion => (eMPQFormatVersion)Header.FormatVersion;
|
||||
public List<string> Files => GetFilePaths();
|
||||
private List<string> FilesOverride = null;
|
||||
|
||||
private List<string> GetFilePaths()
|
||||
{
|
||||
if(FilesOverride != null)
|
||||
{
|
||||
return FilesOverride; // if we were passed in an existing listfile,
|
||||
// don't query again; use the one we were given instead
|
||||
}
|
||||
using (var stream = OpenFile(LISTFILE_NAME))
|
||||
{
|
||||
if (stream == null)
|
||||
|
@ -116,9 +126,10 @@ namespace OpenDiablo2.Common.Models
|
|||
InitializeCryptTable();
|
||||
}
|
||||
|
||||
public MPQ(string path)
|
||||
public MPQ(string path, List<string> listfile = null)
|
||||
{
|
||||
this.Path = path;
|
||||
this.FilesOverride = listfile;
|
||||
|
||||
// If you crash here, you may have Diablo2 open... can't do that :)
|
||||
fileStream = new FileStream(path, FileMode.Open);
|
||||
|
@ -369,6 +380,11 @@ namespace OpenDiablo2.Common.Models
|
|||
return new MPQStream(this, block);
|
||||
}
|
||||
|
||||
public bool HasFile(string filename)
|
||||
{
|
||||
return GetHashRecord(filename, out HashRecord hash);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
fileStream?.Dispose();
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace OpenDiablo2.Common.Models
|
|||
this.blockRecord = blockRecord;
|
||||
this.blockSize = 0x200 << mpq.Header.BlockSize;
|
||||
|
||||
if (blockRecord.IsCompressed && !blockRecord.SingleUnit)
|
||||
if ((blockRecord.IsCompressed || blockRecord.IsImploded) && !blockRecord.SingleUnit)
|
||||
LoadBlockOffsets();
|
||||
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ namespace OpenDiablo2.Common.Models
|
|||
int toread;
|
||||
uint encryptionseed;
|
||||
|
||||
if (blockRecord.IsCompressed)
|
||||
if (blockRecord.IsCompressed || blockRecord.IsImploded)
|
||||
{
|
||||
offset = blockPositions[blockIndex];
|
||||
toread = (int)(blockPositions[blockIndex + 1] - offset);
|
||||
|
@ -226,6 +226,11 @@ namespace OpenDiablo2.Common.Models
|
|||
data = PKDecompress(new MemoryStream(data), expectedLength);
|
||||
}
|
||||
|
||||
if (blockRecord.IsImploded && (toread != expectedLength))
|
||||
{
|
||||
data = PKDecompress(new MemoryStream(data), expectedLength);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ namespace OpenDiablo2.Common.Models.Mobs
|
|||
public double PerVitalityStamina { get; protected set; }
|
||||
public double PerEnergyMana { get; protected set; }
|
||||
|
||||
public int PerLevelStatPoints { get; protected set; }
|
||||
|
||||
public int BaseAttackRating { get; protected set; }
|
||||
public int PerDexterityAttackRating { get; protected set; }
|
||||
|
||||
|
@ -43,7 +45,15 @@ namespace OpenDiablo2.Common.Models.Mobs
|
|||
public int GetHitFrames { get; protected set; }
|
||||
public int BowFrames { get; protected set; }
|
||||
|
||||
public int StartingSkill { get; protected set; }
|
||||
public string StartingSkill { get; protected set; }
|
||||
public string[] StartingSkills { get; protected set; }
|
||||
|
||||
public string AllSkillsBonusString { get; protected set; }
|
||||
public string FirstTabBonusString { get; protected set; }
|
||||
public string SecondTabBonusString { get; protected set; }
|
||||
public string ThirdTabBonusString { get; protected set; }
|
||||
public string ClassOnlyBonusString { get; protected set; }
|
||||
|
||||
public string BaseWeaponClass { get; protected set; }
|
||||
|
||||
public List<InitialEquipment> InitialEquipment { get; }
|
||||
|
@ -52,10 +62,13 @@ namespace OpenDiablo2.Common.Models.Mobs
|
|||
int health, int mana, int stamina, int manaRegen,
|
||||
double perlevelhealth, double perlevelmana, double perlevelstamina,
|
||||
double pervitalityhealth, double pervitalitystamina, double perenergymana,
|
||||
int perLevelStatPoints,
|
||||
int baseatkrating, int basedefrating, int perdexterityatkrating, int perdexteritydefrating,
|
||||
int walkVelocity, int runVelocity, int runDrain,
|
||||
int walkFrames, int runFrames, int swingFrames, int spellFrames, int getHitFrames, int bowFrames,
|
||||
int startingSkill,
|
||||
string startingSkill, string[] startingSkills,
|
||||
string allSkillsBonusString, string firstTabBonusString, string secondTabBonusString,
|
||||
string thirdTabBonusString, string classOnlyBonusString,
|
||||
string baseWeaponClass,
|
||||
List<InitialEquipment> initialEquipment)
|
||||
{
|
||||
|
@ -76,6 +89,8 @@ namespace OpenDiablo2.Common.Models.Mobs
|
|||
PerVitalityStamina = pervitalitystamina;
|
||||
PerEnergyMana = perenergymana;
|
||||
|
||||
PerLevelStatPoints = perLevelStatPoints;
|
||||
|
||||
BaseAttackRating = baseatkrating;
|
||||
BaseDefenseRating = basedefrating;
|
||||
PerDexterityAttackRating = perdexterityatkrating;
|
||||
|
@ -93,6 +108,13 @@ namespace OpenDiablo2.Common.Models.Mobs
|
|||
BowFrames = bowFrames;
|
||||
|
||||
StartingSkill = startingSkill;
|
||||
StartingSkills = startingSkills;
|
||||
AllSkillsBonusString = allSkillsBonusString;
|
||||
FirstTabBonusString = firstTabBonusString;
|
||||
SecondTabBonusString = secondTabBonusString;
|
||||
ThirdTabBonusString = thirdTabBonusString;
|
||||
ClassOnlyBonusString = classOnlyBonusString;
|
||||
|
||||
BaseWeaponClass = baseWeaponClass;
|
||||
|
||||
InitialEquipment = initialEquipment;
|
||||
|
@ -122,29 +144,35 @@ namespace OpenDiablo2.Common.Models.Mobs
|
|||
// RunDrain Comment LifePerLevel StaminaPerLevel ManaPerLevel
|
||||
// 21 22 23
|
||||
// LifePerVitality StaminaPerVitality ManaPerMagic
|
||||
// 24 25 26 27 28 29
|
||||
// 24
|
||||
// StatPerLevel
|
||||
// 25 26 27 28 29 30
|
||||
// #walk #run #swing #spell #gethit #bow
|
||||
// 30 31 32
|
||||
// BlockFactor StartSkill baseWClass
|
||||
// 33 34 35 36 37 38
|
||||
// 31 32
|
||||
// BlockFactor StartSkill
|
||||
// 33 ... 42
|
||||
// Skill1 ... Skill10
|
||||
// 43 44 45 46 47
|
||||
// StrAllSkills StrSkillTab1 StrSkillTab2 StrSkillTab3 StrClassOnly
|
||||
// 48
|
||||
// baseWClass
|
||||
// 49 50 51 49+3 50+3 51+3
|
||||
// item1 item1loc item1count item2 item2loc item2count
|
||||
// 39 40 41 42 43 44
|
||||
// item3 item3loc item3count item4 item4loc item4count
|
||||
// 45 46 47 48 49 50
|
||||
// item5 item5loc item5count item6 item6loc item6count
|
||||
// 51 52 53 54 55 56
|
||||
// item7 item7loc item7count item8 item8loc item8count
|
||||
// 57 58 59 60 61 62
|
||||
// item9 item9loc item9count item10 item10loc item10count
|
||||
// itemn = 49 + (n-1)*3, itemnloc = 50 + (n-1)*3, itemncount = 51 + (n-1)*3
|
||||
|
||||
|
||||
// NEW TODO: StatPerLevel Skill1 ... Skill10
|
||||
// StrAllSkills StrSkillTab1 StrSkillTab2 StrSkillTab3 StrClassOnly
|
||||
|
||||
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)
|
||||
for(int i = 49; i <= 78; i+=3)
|
||||
{
|
||||
var item = new InitialEquipment();
|
||||
item.name = row[i];
|
||||
|
@ -169,21 +197,31 @@ namespace OpenDiablo2.Common.Models.Mobs
|
|||
pervitalityhealth: Convert.ToInt32(row[21]) / 4.0,
|
||||
pervitalitystamina: Convert.ToInt32(row[22]) / 4.0,
|
||||
perenergymana: Convert.ToInt32(row[23]) / 4.0,
|
||||
perLevelStatPoints: Convert.ToInt32(row[24]),
|
||||
baseatkrating: Convert.ToInt32(row[13]),
|
||||
basedefrating: Convert.ToInt32(row[30]),
|
||||
basedefrating: Convert.ToInt32(row[31]),
|
||||
perdexterityatkrating: 5,
|
||||
perdexteritydefrating: 4,
|
||||
walkVelocity: Convert.ToInt32(row[14]),
|
||||
runVelocity: Convert.ToInt32(row[15]),
|
||||
runDrain: Convert.ToInt32(row[16]),
|
||||
walkFrames: Convert.ToInt32(row[24]),
|
||||
runFrames: Convert.ToInt32(row[25]),
|
||||
swingFrames: Convert.ToInt32(row[26]),
|
||||
spellFrames: Convert.ToInt32(row[27]),
|
||||
getHitFrames: Convert.ToInt32(row[28]),
|
||||
bowFrames: Convert.ToInt32(row[29]),
|
||||
startingSkill: Convert.ToInt32(row[31]),
|
||||
baseWeaponClass: row[32],
|
||||
walkFrames: Convert.ToInt32(row[25]),
|
||||
runFrames: Convert.ToInt32(row[26]),
|
||||
swingFrames: Convert.ToInt32(row[27]),
|
||||
spellFrames: Convert.ToInt32(row[28]),
|
||||
getHitFrames: Convert.ToInt32(row[29]),
|
||||
bowFrames: Convert.ToInt32(row[30]),
|
||||
startingSkill: row[32],
|
||||
startingSkills: new string[]
|
||||
{
|
||||
row[33], row[34], row[35], row[36], row[37], row[38], row[39], row[40], row[41], row[42]
|
||||
},
|
||||
allSkillsBonusString: row[43],
|
||||
firstTabBonusString: row[44],
|
||||
secondTabBonusString: row[45],
|
||||
thirdTabBonusString: row[46],
|
||||
classOnlyBonusString: row[47],
|
||||
baseWeaponClass: row[48],
|
||||
initialEquipment: initialEquipment);
|
||||
}
|
||||
}
|
||||
|
|
131
OpenDiablo2.Common/Models/Mobs/MissileTypeConfig.cs
Normal file
131
OpenDiablo2.Common/Models/Mobs/MissileTypeConfig.cs
Normal file
|
@ -0,0 +1,131 @@
|
|||
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 MissileTypeConfig : IMissileTypeConfig
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
public int Id { get; private set; }
|
||||
|
||||
public int BaseVelocity { get; private set; }
|
||||
public int MaxVelocity { get; private set; }
|
||||
public int Acceleration { get; private set; }
|
||||
public int Range { get; private set; }
|
||||
public int ExtraRangePerLevel { get; private set; }
|
||||
|
||||
public int LightRadius { get; private set; }
|
||||
public bool LightFlicker { get; private set; }
|
||||
public byte[] LightColor { get; private set; } // rgb
|
||||
|
||||
public int FramesBeforeVisible { get; private set; } // how many anim frames before it becomes visible
|
||||
public int FramesBeforeActive { get; private set; } // anim frames before it can do anything, e.g. collide
|
||||
public bool LoopAnimation { get; private set; } // true: repeat animation until missile hits range or is otherwise destroyed
|
||||
// false: repeat animation once, then vanish (WARNING: only becomes invisible, not deleted)
|
||||
public string CelFilePath { get; private set; }
|
||||
public int AnimationRate { get; private set; } // does not seem to be used
|
||||
public int AnimationLength { get; private set; } // length of animation for one direction
|
||||
public int AnimationSpeed { get; private set; } // actually used, frames per second
|
||||
public int StartingFrame { get; private set; } // 'randstart' is a misnomer, actually just starts at this frame
|
||||
public bool AnimationHasSubLoop { get; private set; } // if true, will repeat in a certain range of frames
|
||||
//instead of repeating the whole animation again
|
||||
public int AnimationSubLoopStart { get; private set; } // what frame to start at if it has a subloop
|
||||
public int AnimationSubLoopEnd { get; private set; } // what frame to end at in subloop
|
||||
// when it hits this, goes back to subloop start or goes to end if missile is set to die (out of range)
|
||||
|
||||
public MissileTypeConfig(string Name, int Id,
|
||||
int BaseVelocity, int MaxVelocity, int Acceleration, int Range, int ExtraRangePerLevel,
|
||||
int LightRadius, bool LightFlicker, byte[] LightColor,
|
||||
int FramesBeforeVisible, int FramesBeforeActive, bool LoopAnimation, string CelFilePath,
|
||||
int AnimationRate, int AnimationLength, int AnimationSpeed, int StartingFrame,
|
||||
bool AnimationHasSubLoop, int AnimationSubLoopStart, int AnimationSubLoopEnd)
|
||||
{
|
||||
this.Name = Name;
|
||||
this.Id = Id;
|
||||
|
||||
this.BaseVelocity = BaseVelocity;
|
||||
this.MaxVelocity = MaxVelocity;
|
||||
this.Acceleration = Acceleration;
|
||||
this.Range = Range;
|
||||
this.ExtraRangePerLevel = ExtraRangePerLevel;
|
||||
|
||||
this.LightRadius = LightRadius;
|
||||
this.LightFlicker = LightFlicker;
|
||||
this.LightColor = LightColor;
|
||||
|
||||
this.FramesBeforeVisible = FramesBeforeVisible;
|
||||
this.FramesBeforeActive = FramesBeforeActive;
|
||||
this.LoopAnimation = LoopAnimation;
|
||||
this.CelFilePath = CelFilePath;
|
||||
this.AnimationRate = AnimationRate;
|
||||
this.AnimationLength = AnimationLength;
|
||||
this.AnimationSpeed = AnimationSpeed;
|
||||
this.StartingFrame = StartingFrame;
|
||||
this.AnimationHasSubLoop = AnimationHasSubLoop;
|
||||
this.AnimationSubLoopStart = AnimationSubLoopStart;
|
||||
this.AnimationSubLoopEnd = AnimationSubLoopEnd;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MissileTypeConfigHelper
|
||||
{
|
||||
//Missile Id Vel MaxVel Accel Range LevRange
|
||||
//0 1 2 3 4 5 6
|
||||
//Light Flicker Red Green Blue
|
||||
//7 8 9 10 11
|
||||
//InitSteps Activate
|
||||
//12 13
|
||||
//LoopAnim CelFile AnimLen RandStart SubLoop SubStart SubStop
|
||||
//14 15 16 17 18 19 20
|
||||
//CollideType CollideKill CollideFriend LastCollide Collision
|
||||
//21 22 23 24 25
|
||||
//ClientSend NextHit NextDelay Size CanDestroy ToHit AlwaysExplode Explosion
|
||||
//26 27 28 29 30 31 32 33
|
||||
//NeverDup ReturnFire GetHit KnockBack Trans Qty Pierce
|
||||
//34 35 36 37 38 39 40
|
||||
//Param1 Param1 Comment Param2 Param2 Comment SpecialSetup
|
||||
//41 42 43 44 45
|
||||
//Open Beta Skill HitShift SrcDamage MinDamage MaxDamage LevDamage
|
||||
//46 47 48 49 50 51 52 53
|
||||
//EType EMin Emax ELevel ELen ELevelLen HitClass NumDirections LocalBlood
|
||||
//54 55 56 57 58 59 60 61 62
|
||||
|
||||
|
||||
public static IMissileTypeConfig ToMissileTypeConfig(this string[] row)
|
||||
{
|
||||
return new MissileTypeConfig(
|
||||
Name: row[0],
|
||||
Id: Convert.ToInt32(row[1]),
|
||||
|
||||
BaseVelocity: Convert.ToInt32(row[2]),
|
||||
MaxVelocity: Convert.ToInt32(row[3]),
|
||||
Acceleration: Convert.ToInt32(row[4]),
|
||||
Range: Convert.ToInt32(row[5]),
|
||||
ExtraRangePerLevel: Convert.ToInt32(row[6]),
|
||||
|
||||
LightRadius: Convert.ToInt32(row[7]),
|
||||
LightFlicker: (row[8] == "1"),
|
||||
LightColor: new byte[] {Convert.ToByte(row[9]), Convert.ToByte(row[10]), Convert.ToByte(row[11])},
|
||||
|
||||
FramesBeforeVisible: Convert.ToInt32(row[12]),
|
||||
FramesBeforeActive: Convert.ToInt32(row[13]),
|
||||
LoopAnimation: (row[14] == "1"),
|
||||
CelFilePath: row[15],
|
||||
|
||||
// TODO: these rows are wrong! research why our missiles.txt has different columns thatn the one in the guide???
|
||||
// TODO: UNFINISHED
|
||||
AnimationRate: Convert.ToInt32(row[16]),
|
||||
AnimationLength: Convert.ToInt32(row[17]),
|
||||
AnimationSpeed: Convert.ToInt32(row[18]),
|
||||
StartingFrame: Convert.ToInt32(row[19]),
|
||||
AnimationHasSubLoop: (row[20] == "1"),
|
||||
AnimationSubLoopStart: Convert.ToInt32(row[16]),
|
||||
AnimationSubLoopEnd: Convert.ToInt32(row[16])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,6 +105,7 @@
|
|||
<Compile Include="Interfaces\Mobs\IEnemyTypeCombatConfig.cs" />
|
||||
<Compile Include="Interfaces\Mobs\IEnemyTypeConfig.cs" />
|
||||
<Compile Include="Interfaces\Mobs\IEnemyTypeDifficultyConfig.cs" />
|
||||
<Compile Include="Interfaces\Mobs\IMissileTypeConfig.cs" />
|
||||
<Compile Include="Interfaces\UI\ISkillsPanel.cs" />
|
||||
<Compile Include="Models\Mobs\EnemyTypeAppearanceConfig.cs" />
|
||||
<Compile Include="Models\Mobs\EnemyTypeCombatConfig.cs" />
|
||||
|
@ -118,6 +119,7 @@
|
|||
<Compile Include="Models\Item\ItemInstance.cs" />
|
||||
<Compile Include="Models\Item\Misc.cs" />
|
||||
<Compile Include="Models\Item\Weapon.cs" />
|
||||
<Compile Include="Models\Mobs\MissileTypeConfig.cs" />
|
||||
<Compile Include="Models\Mobs\PlayerEquipment.cs" />
|
||||
<Compile Include="Models\MPQCOF.cs" />
|
||||
<Compile Include="Models\MPQDCC.cs" />
|
||||
|
|
|
@ -1,380 +1,383 @@
|
|||
/* 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.Enums;
|
||||
using System;
|
||||
|
||||
namespace OpenDiablo2.Common
|
||||
{
|
||||
public static class ResourcePaths
|
||||
{
|
||||
// --- Loading Screen ---
|
||||
public const string LoadingScreen = @"data\global\ui\Loading\loadingscreen.dc6";
|
||||
|
||||
// --- Main Menu ---
|
||||
public const string GameSelectScreen = @"data\global\ui\FrontEnd\gameselectscreenEXP.dc6";
|
||||
public const string Diablo2LogoFireLeft = @"data\global\ui\FrontEnd\D2logoFireLeft.DC6";
|
||||
public const string Diablo2LogoFireRight = @"data\global\ui\FrontEnd\D2logoFireRight.DC6";
|
||||
public const string Diablo2LogoBlackLeft = @"data\global\ui\FrontEnd\D2logoBlackLeft.DC6";
|
||||
public const string Diablo2LogoBlackRight = @"data\global\ui\FrontEnd\D2logoBlackRight.DC6";
|
||||
|
||||
// --- Credits ---
|
||||
public const string CreditsBackground = @"data\global\ui\CharSelect\creditsbckgexpand.dc6";
|
||||
public const string CreditsText = @"data\local\ui\eng\ExpansionCredits.txt";
|
||||
|
||||
// --- Character Select Screen ---
|
||||
public const string CharacterSelectBackground = @"data\global\ui\FrontEnd\charactercreationscreenEXP.dc6";
|
||||
public const string CharacterSelectCampfire = @"data\global\ui\FrontEnd\fire.DC6";
|
||||
|
||||
public const string CharacterSelectBarbarianUnselected = @"data\global\ui\FrontEnd\barbarian\banu1.DC6";
|
||||
public const string CharacterSelectBarbarianUnselectedH = @"data\global\ui\FrontEnd\barbarian\banu2.DC6";
|
||||
public const string CharacterSelectBarbarianSelected = @"data\global\ui\FrontEnd\barbarian\banu3.DC6";
|
||||
public const string CharacterSelectBarbarianForwardWalk = @"data\global\ui\FrontEnd\barbarian\bafw.DC6";
|
||||
public const string CharacterSelectBarbarianForwardWalkOverlay = @"data\global\ui\FrontEnd\barbarian\BAFWs.DC6";
|
||||
public const string CharacterSelectBarbarianBackWalk = @"data\global\ui\FrontEnd\barbarian\babw.DC6";
|
||||
|
||||
public const string CharacterSelecSorceressUnselected = @"data\global\ui\FrontEnd\sorceress\SONU1.DC6";
|
||||
public const string CharacterSelecSorceressUnselectedH = @"data\global\ui\FrontEnd\sorceress\SONU2.DC6";
|
||||
public const string CharacterSelecSorceressSelected = @"data\global\ui\FrontEnd\sorceress\SONU3.DC6";
|
||||
public const string CharacterSelecSorceressSelectedOverlay = @"data\global\ui\FrontEnd\sorceress\SONU3s.DC6";
|
||||
public const string CharacterSelecSorceressForwardWalk = @"data\global\ui\FrontEnd\sorceress\SOFW.DC6";
|
||||
public const string CharacterSelecSorceressForwardWalkOverlay = @"data\global\ui\FrontEnd\sorceress\SOFWs.DC6";
|
||||
public const string CharacterSelecSorceressBackWalk = @"data\global\ui\FrontEnd\sorceress\SOBW.DC6";
|
||||
public const string CharacterSelecSorceressBackWalkOverlay = @"data\global\ui\FrontEnd\sorceress\SOBWs.DC6";
|
||||
|
||||
public const string CharacterSelectNecromancerUnselected = @"data\global\ui\FrontEnd\necromancer\NENU1.DC6";
|
||||
public const string CharacterSelectNecromancerUnselectedH = @"data\global\ui\FrontEnd\necromancer\NENU2.DC6";
|
||||
public const string CharacterSelecNecromancerSelected = @"data\global\ui\FrontEnd\necromancer\NENU3.DC6";
|
||||
public const string CharacterSelecNecromancerSelectedOverlay = @"data\global\ui\FrontEnd\necromancer\NENU3s.DC6";
|
||||
public const string CharacterSelecNecromancerForwardWalk = @"data\global\ui\FrontEnd\necromancer\NEFW.DC6";
|
||||
public const string CharacterSelecNecromancerForwardWalkOverlay = @"data\global\ui\FrontEnd\necromancer\NEFWs.DC6";
|
||||
public const string CharacterSelecNecromancerBackWalk = @"data\global\ui\FrontEnd\necromancer\NEBW.DC6";
|
||||
public const string CharacterSelecNecromancerBackWalkOverlay = @"data\global\ui\FrontEnd\necromancer\NEBWs.DC6";
|
||||
|
||||
public const string CharacterSelectPaladinUnselected = @"data\global\ui\FrontEnd\paladin\PANU1.DC6";
|
||||
public const string CharacterSelectPaladinUnselectedH = @"data\global\ui\FrontEnd\paladin\PANU2.DC6";
|
||||
public const string CharacterSelecPaladinSelected = @"data\global\ui\FrontEnd\paladin\PANU3.DC6";
|
||||
public const string CharacterSelecPaladinForwardWalk = @"data\global\ui\FrontEnd\paladin\PAFW.DC6";
|
||||
public const string CharacterSelecPaladinForwardWalkOverlay = @"data\global\ui\FrontEnd\paladin\PAFWs.DC6";
|
||||
public const string CharacterSelecPaladinBackWalk = @"data\global\ui\FrontEnd\paladin\PABW.DC6";
|
||||
|
||||
|
||||
public const string CharacterSelectAmazonUnselected = @"data\global\ui\FrontEnd\amazon\AMNU1.DC6";
|
||||
public const string CharacterSelectAmazonUnselectedH = @"data\global\ui\FrontEnd\amazon\AMNU2.DC6";
|
||||
public const string CharacterSelecAmazonSelected = @"data\global\ui\FrontEnd\amazon\AMNU3.DC6";
|
||||
public const string CharacterSelecAmazonForwardWalk = @"data\global\ui\FrontEnd\amazon\AMFW.DC6";
|
||||
public const string CharacterSelecAmazonForwardWalkOverlay = @"data\global\ui\FrontEnd\amazon\AMFWs.DC6";
|
||||
public const string CharacterSelecAmazonBackWalk = @"data\global\ui\FrontEnd\amazon\AMBW.DC6";
|
||||
|
||||
public const string CharacterSelectAssassinUnselected = @"data\global\ui\FrontEnd\assassin\ASNU1.DC6";
|
||||
public const string CharacterSelectAssassinUnselectedH = @"data\global\ui\FrontEnd\assassin\ASNU2.DC6";
|
||||
public const string CharacterSelectAssassinSelected = @"data\global\ui\FrontEnd\assassin\ASNU3.DC6";
|
||||
public const string CharacterSelectAssassinForwardWalk = @"data\global\ui\FrontEnd\assassin\ASFW.DC6";
|
||||
public const string CharacterSelectAssassinBackWalk = @"data\global\ui\FrontEnd\assassin\ASBW.DC6";
|
||||
|
||||
public const string CharacterSelectDruidUnselected = @"data\global\ui\FrontEnd\druid\DZNU1.dc6";
|
||||
public const string CharacterSelectDruidUnselectedH = @"data\global\ui\FrontEnd\druid\DZNU2.dc6";
|
||||
public const string CharacterSelectDruidSelected = @"data\global\ui\FrontEnd\druid\DZNU3.DC6";
|
||||
public const string CharacterSelectDruidForwardWalk = @"data\global\ui\FrontEnd\druid\DZFW.DC6";
|
||||
public const string CharacterSelectDruidBackWalk = @"data\global\ui\FrontEnd\druid\DZBW.DC6";
|
||||
|
||||
// -- Character Selection
|
||||
public const string CharacterSelectionBackground = @"data\global\ui\CharSelect\characterselectscreenEXP.dc6";
|
||||
|
||||
// --- Game ---
|
||||
public const string GamePanels = @"data\global\ui\PANEL\800ctrlpnl7.dc6";
|
||||
public const string GameGlobeOverlap = @"data\global\ui\PANEL\overlap.DC6";
|
||||
public const string HealthMana = @"data\global\ui\PANEL\hlthmana.DC6";
|
||||
public const string GameSmallMenuButton = @"data\global\ui\PANEL\menubutton.DC6"; // TODO: Used for inventory popout
|
||||
public const string SkillIcon = @"data\global\ui\PANEL\Skillicon.DC6"; // TODO: Used for skill icon button
|
||||
public const string AddSkillButton = @"data\global\ui\PANEL\level.DC6";
|
||||
|
||||
// --- Mouse Pointers ---
|
||||
public const string CursorDefault = @"data\global\ui\CURSOR\ohand.DC6";
|
||||
|
||||
// --- Fonts ---
|
||||
public const string Font6 = @"data\local\font\latin\font6";
|
||||
public const string Font8 = @"data\local\font\latin\font8";
|
||||
public const string Font16 = @"data\local\font\latin\font16";
|
||||
public const string Font24 = @"data\local\font\latin\font24";
|
||||
public const string Font30 = @"data\local\font\latin\font30";
|
||||
public const string FontFormal12 = @"data\local\font\latin\fontformal12";
|
||||
public const string FontFormal11 = @"data\local\font\latin\fontformal11";
|
||||
public const string FontFormal10 = @"data\local\font\latin\fontformal10";
|
||||
public const string FontExocet10 = @"data\local\font\latin\fontexocet10";
|
||||
public const string FontExocet8 = @"data\local\font\latin\fontexocet8";
|
||||
|
||||
// --- UI ---
|
||||
public const string WideButtonBlank = @"data\global\ui\FrontEnd\WideButtonBlank.dc6";
|
||||
public const string MediumButtonBlank = @"data\global\ui\FrontEnd\MediumButtonBlank.dc6";
|
||||
public const string CancelButton = @"data\global\ui\FrontEnd\CancelButtonBlank.dc6";
|
||||
public const string NarrowButtonBlank = @"data\global\ui\FrontEnd\NarrowButtonBlank.dc6";
|
||||
public const string ShortButtonBlank = @"data\global\ui\CharSelect\ShortButtonBlank.dc6";
|
||||
public const string TextBox2 = @"data\global\ui\FrontEnd\textbox2.dc6";
|
||||
public const string TallButtonBlank = @"data\global\ui\CharSelect\TallButtonBlank.dc6";
|
||||
|
||||
// --- GAME UI ---
|
||||
public const string MinipanelSmall = @"data\global\ui\PANEL\minipanel_s.dc6";
|
||||
public const string MinipanelButton = @"data\global\ui\PANEL\minipanelbtn.DC6";
|
||||
|
||||
public const string Frame = @"data\global\ui\PANEL\800borderframe.dc6";
|
||||
public const string InventoryCharacterPanel = @"data\global\ui\PANEL\invchar6.DC6";
|
||||
public const string InventoryWeaponsTab = @"data\global\ui\PANEL\invchar6Tab.DC6";
|
||||
public const string SkillsPanelAmazon = @"data\global\ui\SPELLS\skltree_a_back.DC6";
|
||||
public const string SkillsPanelBarbarian = @"data\global\ui\SPELLS\skltree_b_back.DC6";
|
||||
public const string SkillsPanelDruid = @"data\global\ui\SPELLS\skltree_d_back.DC6";
|
||||
public const string SkillsPanelAssassin = @"data\global\ui\SPELLS\skltree_i_back.DC6";
|
||||
public const string SkillsPanelNecromancer = @"data\global\ui\SPELLS\skltree_n_back.DC6";
|
||||
public const string SkillsPanelPaladin = @"data\global\ui\SPELLS\skltree_p_back.DC6";
|
||||
public const string SkillsPanelSorcerer = @"data\global\ui\SPELLS\skltree_s_back.DC6";
|
||||
|
||||
public const string GenericSkills = @"data\global\ui\SPELLS\Skillicon.DC6";
|
||||
public const string AmazonSkills = @"data\global\ui\SPELLS\AmSkillicon.DC6";
|
||||
public const string BarbarianSkills = @"data\global\ui\SPELLS\BaSkillicon.DC6";
|
||||
public const string DruidSkills = @"data\global\ui\SPELLS\DrSkillicon.DC6";
|
||||
public const string AssassinSkills = @"data\global\ui\SPELLS\AsSkillicon.DC6";
|
||||
public const string NecromancerSkills = @"data\global\ui\SPELLS\NeSkillicon.DC6";
|
||||
public const string PaladinSkills = @"data\global\ui\SPELLS\PaSkillicon.DC6";
|
||||
public const string SorcererSkills = @"data\global\ui\SPELLS\SoSkillicon.DC6";
|
||||
|
||||
public const string RunButton = @"data\global\ui\PANEL\runbutton.dc6";
|
||||
public const string MenuButton = @"data\global\ui\PANEL\menubutton.DC6";
|
||||
public const string GoldCoinButton = @"data\global\ui\panel\goldcoinbtn.dc6";
|
||||
public const string SquareButton = @"data\global\ui\panel\buysellbtn.dc6";
|
||||
|
||||
public const string ArmorPlaceholder = @"data\global\ui\PANEL\inv_armor.DC6";
|
||||
public const string BeltPlaceholder = @"data\global\ui\PANEL\inv_belt.DC6";
|
||||
public const string BootsPlaceholder = @"data\global\ui\PANEL\inv_boots.DC6";
|
||||
public const string HelmGlovePlaceholder = @"data\global\ui\PANEL\inv_helm_glove.DC6";
|
||||
public const string RingAmuletPlaceholder = @"data\global\ui\PANEL\inv_ring_amulet.DC6";
|
||||
public const string WeaponsPlaceholder = @"data\global\ui\PANEL\inv_weapons.DC6";
|
||||
|
||||
// --- Data ---
|
||||
public const string EnglishTable = @"data\local\lng\eng\English.txt";
|
||||
public const string ExpansionStringTable = @"data\local\lng\eng\expansionstring.tbl";
|
||||
public const string LevelPreset = @"data\global\excel\LvlPrest.txt";
|
||||
public const string LevelType = @"data\global\excel\LvlTypes.txt";
|
||||
public const string LevelDetails = @"data\global\excel\Levels.txt";
|
||||
public const string ObjectDetails = @"data\global\excel\Objects.txt";
|
||||
|
||||
// --- Animations ---
|
||||
public const string ObjectData = @"data\global\objects";
|
||||
public const string AnimationData = @"data\global\animdata.d2";
|
||||
public const string PlayerAnimationBase = @"data\global\CHARS";
|
||||
|
||||
// --- Inventory Data ---
|
||||
public const string Weapons = @"data\global\excel\weapons.txt";
|
||||
public const string Armor = @"data\global\excel\armor.txt";
|
||||
public const string Misc = @"data\global\excel\misc.txt";
|
||||
|
||||
// --- Character Data ---
|
||||
public const string Experience = @"data\global\excel\experience.txt";
|
||||
public const string CharStats = @"data\global\excel\charstats.txt";
|
||||
|
||||
// --- Music ---
|
||||
public const string BGMTitle = @"data\global\music\introedit.wav";
|
||||
public const string BGMOptions = @"data\global\music\Common\options.wav";
|
||||
public const string BGMAct1AndarielAction = @"data\global\music\Act1\andarielaction.wav";
|
||||
public const string BGMAct1BloodRavenResolution = @"data\global\music\Act1\bloodravenresolution.wav";
|
||||
public const string BGMAct1Caves = @"data\global\music\Act1\caves.wav";
|
||||
public const string BGMAct1Crypt = @"data\global\music\Act1\crypt.wav";
|
||||
public const string BGMAct1DenOfEvilAction = @"data\global\music\Act1\denofevilaction.wav";
|
||||
public const string BGMAct1Monastery = @"data\global\music\Act1\monastery.wav";
|
||||
public const string BGMAct1Town1 = @"data\global\music\Act1\town1.wav";
|
||||
public const string BGMAct1Tristram = @"data\global\music\Act1\tristram.wav";
|
||||
public const string BGMAct1Wild = @"data\global\music\Act1\wild.wav";
|
||||
public const string BGMAct2Desert = @"data\global\music\Act2\desert.wav";
|
||||
public const string BGMAct2Harem = @"data\global\music\Act2\harem.wav";
|
||||
public const string BGMAct2HoradricAction = @"data\global\music\Act2\horadricaction.wav";
|
||||
public const string BGMAct2Lair = @"data\global\music\Act2\lair.wav";
|
||||
public const string BGMAct2RadamentResolution = @"data\global\music\Act2\radamentresolution.wav";
|
||||
public const string BGMAct2Sanctuary = @"data\global\music\Act2\sanctuary.wav";
|
||||
public const string BGMAct2Sewer = @"data\global\music\Act2\sewer.wav";
|
||||
public const string BGMAct2TaintedSunAction = @"data\global\music\Act2\taintedsunaction.wav";
|
||||
public const string BGMAct2Tombs = @"data\global\music\Act2\tombs.wav";
|
||||
public const string BGMAct2Town2 = @"data\global\music\Act2\town2.wav";
|
||||
public const string BGMAct2Valley = @"data\global\music\Act2\valley.wav";
|
||||
public const string BGMAct3Jungle = @"data\global\music\Act3\jungle.wav";
|
||||
public const string BGMAct3Kurast = @"data\global\music\Act3\kurast.wav";
|
||||
public const string BGMAct3KurastSewer = @"data\global\music\Act3\kurastsewer.wav";
|
||||
public const string BGMAct3MefDeathAction = @"data\global\music\Act3\mefdeathaction.wav";
|
||||
public const string BGMAct3OrbAction = @"data\global\music\Act3\orbaction.wav";
|
||||
public const string BGMAct3Spider = @"data\global\music\Act3\spider.wav";
|
||||
public const string BGMAct3Town3 = @"data\global\music\Act3\town3.wav";
|
||||
public const string BGMAct4Diablo = @"data\global\music\Act4\diablo.wav";
|
||||
public const string BGMAct4DiabloAction = @"data\global\music\Act4\diabloaction.wav";
|
||||
public const string BGMAct4ForgeAction = @"data\global\music\Act4\forgeaction.wav";
|
||||
public const string BGMAct4IzualAction = @"data\global\music\Act4\izualaction.wav";
|
||||
public const string BGMAct4Mesa = @"data\global\music\Act4\mesa.wav";
|
||||
public const string BGMAct4Town4 = @"data\global\music\Act4\town4.wav";
|
||||
public const string BGMAct5Baal = @"data\global\music\Act5\baal.wav";
|
||||
public const string BGMAct5XTown = @"data\global\music\Act5\xtown.wav";
|
||||
|
||||
|
||||
// --- Sound Effects ---
|
||||
public const string SFXButtonClick = @"data\global\sfx\Cursor\button.wav";
|
||||
public const string SFXAmazonDeselect = @"data\global\sfx\Cursor\intro\amazon deselect.wav";
|
||||
public const string SFXAmazonSelect = @"data\global\sfx\Cursor\intro\amazon select.wav";
|
||||
public const string SFXAssassinDeselect = @"data\global\sfx\Cursor\intro\assassin deselect.wav";
|
||||
public const string SFXAssassinSelect = @"data\global\sfx\Cursor\intro\assassin select.wav";
|
||||
public const string SFXBarbarianDeselect = @"data\global\sfx\Cursor\intro\barbarian deselect.wav";
|
||||
public const string SFXBarbarianSelect = @"data\global\sfx\Cursor\intro\barbarian select.wav";
|
||||
public const string SFXDruidDeselect = @"data\global\sfx\Cursor\intro\druid deselect.wav";
|
||||
public const string SFXDruidSelect = @"data\global\sfx\Cursor\intro\druid select.wav";
|
||||
public const string SFXNecromancerDeselect = @"data\global\sfx\Cursor\intro\necromancer deselect.wav";
|
||||
public const string SFXNecromancerSelect = @"data\global\sfx\Cursor\intro\necromancer select.wav";
|
||||
public const string SFXPaladinDeselect = @"data\global\sfx\Cursor\intro\paladin deselect.wav";
|
||||
public const string SFXPaladinSelect = @"data\global\sfx\Cursor\intro\paladin select.wav";
|
||||
public const string SFXSorceressDeselect = @"data\global\sfx\Cursor\intro\sorceress deselect.wav";
|
||||
public const string SFXSorceressSelect = @"data\global\sfx\Cursor\intro\sorceress select.wav";
|
||||
|
||||
// --- Enemy Data ---
|
||||
public static string MonStats = "data\\global\\excel\\monstats.txt";
|
||||
|
||||
public static string GeneratePathForItem(string spriteName)
|
||||
{
|
||||
return $@"data\global\items\{spriteName}.dc6";
|
||||
}
|
||||
|
||||
public static string GetMusicPathForLevel(eLevelId levelId)
|
||||
{
|
||||
switch (levelId)
|
||||
{
|
||||
case eLevelId.None:
|
||||
return string.Empty;
|
||||
case eLevelId.Act1_Town1:
|
||||
return BGMAct1Town1;
|
||||
case eLevelId.Act1_CaveTreasure2:
|
||||
return BGMAct1Caves;
|
||||
case eLevelId.Act1_CaveTreasure3:
|
||||
return BGMAct1Caves;
|
||||
case eLevelId.Act1_CaveTreasure4:
|
||||
return BGMAct1Caves;
|
||||
case eLevelId.Act1_CaveTreasure5:
|
||||
return BGMAct1Caves;
|
||||
case eLevelId.Act1_CryptCountessX:
|
||||
return BGMAct1BloodRavenResolution; // TODO: Verify
|
||||
case eLevelId.Act1_Tower2:
|
||||
return BGMAct1Caves; // TODO: Verify
|
||||
case eLevelId.Act1_MonFront:
|
||||
return BGMAct1DenOfEvilAction; // TODO: Verify
|
||||
case eLevelId.Act1_Courtyard1:
|
||||
return BGMAct1Monastery; // TODO: Verify
|
||||
case eLevelId.Act1_Courtyard2:
|
||||
return BGMAct1Monastery; // TODO: Verify
|
||||
case eLevelId.Act1_Cathedral:
|
||||
return BGMAct1Monastery; // TODO: Verify
|
||||
case eLevelId.Act1_Andariel:
|
||||
return BGMAct1AndarielAction;
|
||||
case eLevelId.Act1_Tristram:
|
||||
return BGMAct1Tristram;
|
||||
case eLevelId.Act2_Town:
|
||||
return BGMAct2Town2;
|
||||
case eLevelId.Act2_Harem:
|
||||
return BGMAct2Harem;
|
||||
case eLevelId.Act2_DurielsLair:
|
||||
return BGMAct2Lair;
|
||||
case eLevelId.Act3_Town:
|
||||
return BGMAct3Town3;
|
||||
case eLevelId.Act3_DungeonTreasure1:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_DungeonTreasure2:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_SewerTreasureX:
|
||||
return BGMAct3KurastSewer; // TODO: Verify
|
||||
case eLevelId.Act3_Temple1:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_Temple2:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_Temple3:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_Temple4:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_Temple5:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_Temple6:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_MephistoComplex:
|
||||
return BGMAct3MefDeathAction; // TODO: Verify
|
||||
case eLevelId.Act4_Fortress:
|
||||
return BGMAct4Mesa; // TODO: Verify
|
||||
case eLevelId.Act5_Town:
|
||||
return BGMAct5XTown;
|
||||
case eLevelId.Act5_TempleFinalRoom:
|
||||
return BGMAct2Sanctuary; // TODO: Verify
|
||||
case eLevelId.Act5_ThroneRoom:
|
||||
return BGMAct2Sanctuary; // TODO: Verify
|
||||
case eLevelId.Act5_WorldStone:
|
||||
return BGMAct4ForgeAction; // TODO: Verify
|
||||
case eLevelId.Act5_TempleEntrance:
|
||||
return BGMAct5Baal; // TODO: Verify
|
||||
case eLevelId.Act5_BaalEntrance:
|
||||
return BGMAct5Baal; // TODO: Verify
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetHeroSkillPanel(eHero hero)
|
||||
{
|
||||
switch (hero)
|
||||
{
|
||||
case eHero.Amazon:
|
||||
return SkillsPanelAmazon;
|
||||
case eHero.Assassin:
|
||||
return SkillsPanelAssassin;
|
||||
case eHero.Barbarian:
|
||||
return SkillsPanelBarbarian;
|
||||
case eHero.Druid:
|
||||
return SkillsPanelDruid;
|
||||
case eHero.Necromancer:
|
||||
return SkillsPanelNecromancer;
|
||||
case eHero.Paladin:
|
||||
return SkillsPanelPaladin;
|
||||
case eHero.Sorceress:
|
||||
return SkillsPanelSorcerer;
|
||||
default:
|
||||
throw new ArgumentException($"Unknown hero type: {hero}");
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetHeroSkillsIcons(eHero hero)
|
||||
{
|
||||
switch (hero)
|
||||
{
|
||||
case eHero.None:
|
||||
return GenericSkills;
|
||||
case eHero.Amazon:
|
||||
return AmazonSkills;
|
||||
case eHero.Assassin:
|
||||
return AssassinSkills;
|
||||
case eHero.Barbarian:
|
||||
return BarbarianSkills;
|
||||
case eHero.Druid:
|
||||
return DruidSkills;
|
||||
case eHero.Necromancer:
|
||||
return NecromancerSkills;
|
||||
case eHero.Paladin:
|
||||
return PaladinSkills;
|
||||
case eHero.Sorceress:
|
||||
return SorcererSkills;
|
||||
default:
|
||||
throw new ArgumentException($"Unknown hero type: {hero}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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.Enums;
|
||||
using System;
|
||||
|
||||
namespace OpenDiablo2.Common
|
||||
{
|
||||
public static class ResourcePaths
|
||||
{
|
||||
// --- Loading Screen ---
|
||||
public const string LoadingScreen = @"data\global\ui\Loading\loadingscreen.dc6";
|
||||
|
||||
// --- Main Menu ---
|
||||
public const string GameSelectScreen = @"data\global\ui\FrontEnd\gameselectscreenEXP.dc6";
|
||||
public const string Diablo2LogoFireLeft = @"data\global\ui\FrontEnd\D2logoFireLeft.DC6";
|
||||
public const string Diablo2LogoFireRight = @"data\global\ui\FrontEnd\D2logoFireRight.DC6";
|
||||
public const string Diablo2LogoBlackLeft = @"data\global\ui\FrontEnd\D2logoBlackLeft.DC6";
|
||||
public const string Diablo2LogoBlackRight = @"data\global\ui\FrontEnd\D2logoBlackRight.DC6";
|
||||
|
||||
// --- Credits ---
|
||||
public const string CreditsBackground = @"data\global\ui\CharSelect\creditsbckgexpand.dc6";
|
||||
public const string CreditsText = @"data\local\ui\eng\ExpansionCredits.txt";
|
||||
|
||||
// --- Character Select Screen ---
|
||||
public const string CharacterSelectBackground = @"data\global\ui\FrontEnd\charactercreationscreenEXP.dc6";
|
||||
public const string CharacterSelectCampfire = @"data\global\ui\FrontEnd\fire.DC6";
|
||||
|
||||
public const string CharacterSelectBarbarianUnselected = @"data\global\ui\FrontEnd\barbarian\banu1.DC6";
|
||||
public const string CharacterSelectBarbarianUnselectedH = @"data\global\ui\FrontEnd\barbarian\banu2.DC6";
|
||||
public const string CharacterSelectBarbarianSelected = @"data\global\ui\FrontEnd\barbarian\banu3.DC6";
|
||||
public const string CharacterSelectBarbarianForwardWalk = @"data\global\ui\FrontEnd\barbarian\bafw.DC6";
|
||||
public const string CharacterSelectBarbarianForwardWalkOverlay = @"data\global\ui\FrontEnd\barbarian\BAFWs.DC6";
|
||||
public const string CharacterSelectBarbarianBackWalk = @"data\global\ui\FrontEnd\barbarian\babw.DC6";
|
||||
|
||||
public const string CharacterSelecSorceressUnselected = @"data\global\ui\FrontEnd\sorceress\SONU1.DC6";
|
||||
public const string CharacterSelecSorceressUnselectedH = @"data\global\ui\FrontEnd\sorceress\SONU2.DC6";
|
||||
public const string CharacterSelecSorceressSelected = @"data\global\ui\FrontEnd\sorceress\SONU3.DC6";
|
||||
public const string CharacterSelecSorceressSelectedOverlay = @"data\global\ui\FrontEnd\sorceress\SONU3s.DC6";
|
||||
public const string CharacterSelecSorceressForwardWalk = @"data\global\ui\FrontEnd\sorceress\SOFW.DC6";
|
||||
public const string CharacterSelecSorceressForwardWalkOverlay = @"data\global\ui\FrontEnd\sorceress\SOFWs.DC6";
|
||||
public const string CharacterSelecSorceressBackWalk = @"data\global\ui\FrontEnd\sorceress\SOBW.DC6";
|
||||
public const string CharacterSelecSorceressBackWalkOverlay = @"data\global\ui\FrontEnd\sorceress\SOBWs.DC6";
|
||||
|
||||
public const string CharacterSelectNecromancerUnselected = @"data\global\ui\FrontEnd\necromancer\NENU1.DC6";
|
||||
public const string CharacterSelectNecromancerUnselectedH = @"data\global\ui\FrontEnd\necromancer\NENU2.DC6";
|
||||
public const string CharacterSelecNecromancerSelected = @"data\global\ui\FrontEnd\necromancer\NENU3.DC6";
|
||||
public const string CharacterSelecNecromancerSelectedOverlay = @"data\global\ui\FrontEnd\necromancer\NENU3s.DC6";
|
||||
public const string CharacterSelecNecromancerForwardWalk = @"data\global\ui\FrontEnd\necromancer\NEFW.DC6";
|
||||
public const string CharacterSelecNecromancerForwardWalkOverlay = @"data\global\ui\FrontEnd\necromancer\NEFWs.DC6";
|
||||
public const string CharacterSelecNecromancerBackWalk = @"data\global\ui\FrontEnd\necromancer\NEBW.DC6";
|
||||
public const string CharacterSelecNecromancerBackWalkOverlay = @"data\global\ui\FrontEnd\necromancer\NEBWs.DC6";
|
||||
|
||||
public const string CharacterSelectPaladinUnselected = @"data\global\ui\FrontEnd\paladin\PANU1.DC6";
|
||||
public const string CharacterSelectPaladinUnselectedH = @"data\global\ui\FrontEnd\paladin\PANU2.DC6";
|
||||
public const string CharacterSelecPaladinSelected = @"data\global\ui\FrontEnd\paladin\PANU3.DC6";
|
||||
public const string CharacterSelecPaladinForwardWalk = @"data\global\ui\FrontEnd\paladin\PAFW.DC6";
|
||||
public const string CharacterSelecPaladinForwardWalkOverlay = @"data\global\ui\FrontEnd\paladin\PAFWs.DC6";
|
||||
public const string CharacterSelecPaladinBackWalk = @"data\global\ui\FrontEnd\paladin\PABW.DC6";
|
||||
|
||||
|
||||
public const string CharacterSelectAmazonUnselected = @"data\global\ui\FrontEnd\amazon\AMNU1.DC6";
|
||||
public const string CharacterSelectAmazonUnselectedH = @"data\global\ui\FrontEnd\amazon\AMNU2.DC6";
|
||||
public const string CharacterSelecAmazonSelected = @"data\global\ui\FrontEnd\amazon\AMNU3.DC6";
|
||||
public const string CharacterSelecAmazonForwardWalk = @"data\global\ui\FrontEnd\amazon\AMFW.DC6";
|
||||
public const string CharacterSelecAmazonForwardWalkOverlay = @"data\global\ui\FrontEnd\amazon\AMFWs.DC6";
|
||||
public const string CharacterSelecAmazonBackWalk = @"data\global\ui\FrontEnd\amazon\AMBW.DC6";
|
||||
|
||||
public const string CharacterSelectAssassinUnselected = @"data\global\ui\FrontEnd\assassin\ASNU1.DC6";
|
||||
public const string CharacterSelectAssassinUnselectedH = @"data\global\ui\FrontEnd\assassin\ASNU2.DC6";
|
||||
public const string CharacterSelectAssassinSelected = @"data\global\ui\FrontEnd\assassin\ASNU3.DC6";
|
||||
public const string CharacterSelectAssassinForwardWalk = @"data\global\ui\FrontEnd\assassin\ASFW.DC6";
|
||||
public const string CharacterSelectAssassinBackWalk = @"data\global\ui\FrontEnd\assassin\ASBW.DC6";
|
||||
|
||||
public const string CharacterSelectDruidUnselected = @"data\global\ui\FrontEnd\druid\DZNU1.dc6";
|
||||
public const string CharacterSelectDruidUnselectedH = @"data\global\ui\FrontEnd\druid\DZNU2.dc6";
|
||||
public const string CharacterSelectDruidSelected = @"data\global\ui\FrontEnd\druid\DZNU3.DC6";
|
||||
public const string CharacterSelectDruidForwardWalk = @"data\global\ui\FrontEnd\druid\DZFW.DC6";
|
||||
public const string CharacterSelectDruidBackWalk = @"data\global\ui\FrontEnd\druid\DZBW.DC6";
|
||||
|
||||
// -- Character Selection
|
||||
public const string CharacterSelectionBackground = @"data\global\ui\CharSelect\characterselectscreenEXP.dc6";
|
||||
|
||||
// --- Game ---
|
||||
public const string GamePanels = @"data\global\ui\PANEL\800ctrlpnl7.dc6";
|
||||
public const string GameGlobeOverlap = @"data\global\ui\PANEL\overlap.DC6";
|
||||
public const string HealthMana = @"data\global\ui\PANEL\hlthmana.DC6";
|
||||
public const string GameSmallMenuButton = @"data\global\ui\PANEL\menubutton.DC6"; // TODO: Used for inventory popout
|
||||
public const string SkillIcon = @"data\global\ui\PANEL\Skillicon.DC6"; // TODO: Used for skill icon button
|
||||
public const string AddSkillButton = @"data\global\ui\PANEL\level.DC6";
|
||||
|
||||
// --- Mouse Pointers ---
|
||||
public const string CursorDefault = @"data\global\ui\CURSOR\ohand.DC6";
|
||||
|
||||
// --- Fonts ---
|
||||
public const string Font6 = @"data\local\font\latin\font6";
|
||||
public const string Font8 = @"data\local\font\latin\font8";
|
||||
public const string Font16 = @"data\local\font\latin\font16";
|
||||
public const string Font24 = @"data\local\font\latin\font24";
|
||||
public const string Font30 = @"data\local\font\latin\font30";
|
||||
public const string FontFormal12 = @"data\local\font\latin\fontformal12";
|
||||
public const string FontFormal11 = @"data\local\font\latin\fontformal11";
|
||||
public const string FontFormal10 = @"data\local\font\latin\fontformal10";
|
||||
public const string FontExocet10 = @"data\local\font\latin\fontexocet10";
|
||||
public const string FontExocet8 = @"data\local\font\latin\fontexocet8";
|
||||
|
||||
// --- UI ---
|
||||
public const string WideButtonBlank = @"data\global\ui\FrontEnd\WideButtonBlank.dc6";
|
||||
public const string MediumButtonBlank = @"data\global\ui\FrontEnd\MediumButtonBlank.dc6";
|
||||
public const string CancelButton = @"data\global\ui\FrontEnd\CancelButtonBlank.dc6";
|
||||
public const string NarrowButtonBlank = @"data\global\ui\FrontEnd\NarrowButtonBlank.dc6";
|
||||
public const string ShortButtonBlank = @"data\global\ui\CharSelect\ShortButtonBlank.dc6";
|
||||
public const string TextBox2 = @"data\global\ui\FrontEnd\textbox2.dc6";
|
||||
public const string TallButtonBlank = @"data\global\ui\CharSelect\TallButtonBlank.dc6";
|
||||
|
||||
// --- GAME UI ---
|
||||
public const string MinipanelSmall = @"data\global\ui\PANEL\minipanel_s.dc6";
|
||||
public const string MinipanelButton = @"data\global\ui\PANEL\minipanelbtn.DC6";
|
||||
|
||||
public const string Frame = @"data\global\ui\PANEL\800borderframe.dc6";
|
||||
public const string InventoryCharacterPanel = @"data\global\ui\PANEL\invchar6.DC6";
|
||||
public const string InventoryWeaponsTab = @"data\global\ui\PANEL\invchar6Tab.DC6";
|
||||
public const string SkillsPanelAmazon = @"data\global\ui\SPELLS\skltree_a_back.DC6";
|
||||
public const string SkillsPanelBarbarian = @"data\global\ui\SPELLS\skltree_b_back.DC6";
|
||||
public const string SkillsPanelDruid = @"data\global\ui\SPELLS\skltree_d_back.DC6";
|
||||
public const string SkillsPanelAssassin = @"data\global\ui\SPELLS\skltree_i_back.DC6";
|
||||
public const string SkillsPanelNecromancer = @"data\global\ui\SPELLS\skltree_n_back.DC6";
|
||||
public const string SkillsPanelPaladin = @"data\global\ui\SPELLS\skltree_p_back.DC6";
|
||||
public const string SkillsPanelSorcerer = @"data\global\ui\SPELLS\skltree_s_back.DC6";
|
||||
|
||||
public const string GenericSkills = @"data\global\ui\SPELLS\Skillicon.DC6";
|
||||
public const string AmazonSkills = @"data\global\ui\SPELLS\AmSkillicon.DC6";
|
||||
public const string BarbarianSkills = @"data\global\ui\SPELLS\BaSkillicon.DC6";
|
||||
public const string DruidSkills = @"data\global\ui\SPELLS\DrSkillicon.DC6";
|
||||
public const string AssassinSkills = @"data\global\ui\SPELLS\AsSkillicon.DC6";
|
||||
public const string NecromancerSkills = @"data\global\ui\SPELLS\NeSkillicon.DC6";
|
||||
public const string PaladinSkills = @"data\global\ui\SPELLS\PaSkillicon.DC6";
|
||||
public const string SorcererSkills = @"data\global\ui\SPELLS\SoSkillicon.DC6";
|
||||
|
||||
public const string RunButton = @"data\global\ui\PANEL\runbutton.dc6";
|
||||
public const string MenuButton = @"data\global\ui\PANEL\menubutton.DC6";
|
||||
public const string GoldCoinButton = @"data\global\ui\panel\goldcoinbtn.dc6";
|
||||
public const string SquareButton = @"data\global\ui\panel\buysellbtn.dc6";
|
||||
|
||||
public const string ArmorPlaceholder = @"data\global\ui\PANEL\inv_armor.DC6";
|
||||
public const string BeltPlaceholder = @"data\global\ui\PANEL\inv_belt.DC6";
|
||||
public const string BootsPlaceholder = @"data\global\ui\PANEL\inv_boots.DC6";
|
||||
public const string HelmGlovePlaceholder = @"data\global\ui\PANEL\inv_helm_glove.DC6";
|
||||
public const string RingAmuletPlaceholder = @"data\global\ui\PANEL\inv_ring_amulet.DC6";
|
||||
public const string WeaponsPlaceholder = @"data\global\ui\PANEL\inv_weapons.DC6";
|
||||
|
||||
// --- Data ---
|
||||
public const string EnglishTable = @"data\local\lng\eng\English.txt";
|
||||
public const string ExpansionStringTable = @"data\local\lng\eng\expansionstring.tbl";
|
||||
public const string LevelPreset = @"data\global\excel\LvlPrest.txt";
|
||||
public const string LevelType = @"data\global\excel\LvlTypes.txt";
|
||||
public const string LevelDetails = @"data\global\excel\Levels.txt";
|
||||
public const string ObjectDetails = @"data\global\excel\Objects.txt";
|
||||
|
||||
// --- Animations ---
|
||||
public const string ObjectData = @"data\global\objects";
|
||||
public const string AnimationData = @"data\global\animdata.d2";
|
||||
public const string PlayerAnimationBase = @"data\global\CHARS";
|
||||
|
||||
// --- Inventory Data ---
|
||||
public const string Weapons = @"data\global\excel\weapons.txt";
|
||||
public const string Armor = @"data\global\excel\armor.txt";
|
||||
public const string Misc = @"data\global\excel\misc.txt";
|
||||
|
||||
// --- Character Data ---
|
||||
public const string Experience = @"data\global\excel\experience.txt";
|
||||
public const string CharStats = @"data\global\excel\charstats.txt";
|
||||
|
||||
// --- Music ---
|
||||
public const string BGMTitle = @"data\global\music\introedit.wav";
|
||||
public const string BGMOptions = @"data\global\music\Common\options.wav";
|
||||
public const string BGMAct1AndarielAction = @"data\global\music\Act1\andarielaction.wav";
|
||||
public const string BGMAct1BloodRavenResolution = @"data\global\music\Act1\bloodravenresolution.wav";
|
||||
public const string BGMAct1Caves = @"data\global\music\Act1\caves.wav";
|
||||
public const string BGMAct1Crypt = @"data\global\music\Act1\crypt.wav";
|
||||
public const string BGMAct1DenOfEvilAction = @"data\global\music\Act1\denofevilaction.wav";
|
||||
public const string BGMAct1Monastery = @"data\global\music\Act1\monastery.wav";
|
||||
public const string BGMAct1Town1 = @"data\global\music\Act1\town1.wav";
|
||||
public const string BGMAct1Tristram = @"data\global\music\Act1\tristram.wav";
|
||||
public const string BGMAct1Wild = @"data\global\music\Act1\wild.wav";
|
||||
public const string BGMAct2Desert = @"data\global\music\Act2\desert.wav";
|
||||
public const string BGMAct2Harem = @"data\global\music\Act2\harem.wav";
|
||||
public const string BGMAct2HoradricAction = @"data\global\music\Act2\horadricaction.wav";
|
||||
public const string BGMAct2Lair = @"data\global\music\Act2\lair.wav";
|
||||
public const string BGMAct2RadamentResolution = @"data\global\music\Act2\radamentresolution.wav";
|
||||
public const string BGMAct2Sanctuary = @"data\global\music\Act2\sanctuary.wav";
|
||||
public const string BGMAct2Sewer = @"data\global\music\Act2\sewer.wav";
|
||||
public const string BGMAct2TaintedSunAction = @"data\global\music\Act2\taintedsunaction.wav";
|
||||
public const string BGMAct2Tombs = @"data\global\music\Act2\tombs.wav";
|
||||
public const string BGMAct2Town2 = @"data\global\music\Act2\town2.wav";
|
||||
public const string BGMAct2Valley = @"data\global\music\Act2\valley.wav";
|
||||
public const string BGMAct3Jungle = @"data\global\music\Act3\jungle.wav";
|
||||
public const string BGMAct3Kurast = @"data\global\music\Act3\kurast.wav";
|
||||
public const string BGMAct3KurastSewer = @"data\global\music\Act3\kurastsewer.wav";
|
||||
public const string BGMAct3MefDeathAction = @"data\global\music\Act3\mefdeathaction.wav";
|
||||
public const string BGMAct3OrbAction = @"data\global\music\Act3\orbaction.wav";
|
||||
public const string BGMAct3Spider = @"data\global\music\Act3\spider.wav";
|
||||
public const string BGMAct3Town3 = @"data\global\music\Act3\town3.wav";
|
||||
public const string BGMAct4Diablo = @"data\global\music\Act4\diablo.wav";
|
||||
public const string BGMAct4DiabloAction = @"data\global\music\Act4\diabloaction.wav";
|
||||
public const string BGMAct4ForgeAction = @"data\global\music\Act4\forgeaction.wav";
|
||||
public const string BGMAct4IzualAction = @"data\global\music\Act4\izualaction.wav";
|
||||
public const string BGMAct4Mesa = @"data\global\music\Act4\mesa.wav";
|
||||
public const string BGMAct4Town4 = @"data\global\music\Act4\town4.wav";
|
||||
public const string BGMAct5Baal = @"data\global\music\Act5\baal.wav";
|
||||
public const string BGMAct5XTown = @"data\global\music\Act5\xtown.wav";
|
||||
|
||||
|
||||
// --- Sound Effects ---
|
||||
public const string SFXButtonClick = @"data\global\sfx\Cursor\button.wav";
|
||||
public const string SFXAmazonDeselect = @"data\global\sfx\Cursor\intro\amazon deselect.wav";
|
||||
public const string SFXAmazonSelect = @"data\global\sfx\Cursor\intro\amazon select.wav";
|
||||
public const string SFXAssassinDeselect = @"data\global\sfx\Cursor\intro\assassin deselect.wav";
|
||||
public const string SFXAssassinSelect = @"data\global\sfx\Cursor\intro\assassin select.wav";
|
||||
public const string SFXBarbarianDeselect = @"data\global\sfx\Cursor\intro\barbarian deselect.wav";
|
||||
public const string SFXBarbarianSelect = @"data\global\sfx\Cursor\intro\barbarian select.wav";
|
||||
public const string SFXDruidDeselect = @"data\global\sfx\Cursor\intro\druid deselect.wav";
|
||||
public const string SFXDruidSelect = @"data\global\sfx\Cursor\intro\druid select.wav";
|
||||
public const string SFXNecromancerDeselect = @"data\global\sfx\Cursor\intro\necromancer deselect.wav";
|
||||
public const string SFXNecromancerSelect = @"data\global\sfx\Cursor\intro\necromancer select.wav";
|
||||
public const string SFXPaladinDeselect = @"data\global\sfx\Cursor\intro\paladin deselect.wav";
|
||||
public const string SFXPaladinSelect = @"data\global\sfx\Cursor\intro\paladin select.wav";
|
||||
public const string SFXSorceressDeselect = @"data\global\sfx\Cursor\intro\sorceress deselect.wav";
|
||||
public const string SFXSorceressSelect = @"data\global\sfx\Cursor\intro\sorceress select.wav";
|
||||
|
||||
// --- Enemy Data ---
|
||||
public static string MonStats = "data\\global\\excel\\monstats.txt";
|
||||
|
||||
// --- Skill Data ---
|
||||
public static string Missiles = "data\\global\\excel\\missiles.txt";
|
||||
|
||||
public static string GeneratePathForItem(string spriteName)
|
||||
{
|
||||
return $@"data\global\items\{spriteName}.dc6";
|
||||
}
|
||||
|
||||
public static string GetMusicPathForLevel(eLevelId levelId)
|
||||
{
|
||||
switch (levelId)
|
||||
{
|
||||
case eLevelId.None:
|
||||
return string.Empty;
|
||||
case eLevelId.Act1_Town1:
|
||||
return BGMAct1Town1;
|
||||
case eLevelId.Act1_CaveTreasure2:
|
||||
return BGMAct1Caves;
|
||||
case eLevelId.Act1_CaveTreasure3:
|
||||
return BGMAct1Caves;
|
||||
case eLevelId.Act1_CaveTreasure4:
|
||||
return BGMAct1Caves;
|
||||
case eLevelId.Act1_CaveTreasure5:
|
||||
return BGMAct1Caves;
|
||||
case eLevelId.Act1_CryptCountessX:
|
||||
return BGMAct1BloodRavenResolution; // TODO: Verify
|
||||
case eLevelId.Act1_Tower2:
|
||||
return BGMAct1Caves; // TODO: Verify
|
||||
case eLevelId.Act1_MonFront:
|
||||
return BGMAct1DenOfEvilAction; // TODO: Verify
|
||||
case eLevelId.Act1_Courtyard1:
|
||||
return BGMAct1Monastery; // TODO: Verify
|
||||
case eLevelId.Act1_Courtyard2:
|
||||
return BGMAct1Monastery; // TODO: Verify
|
||||
case eLevelId.Act1_Cathedral:
|
||||
return BGMAct1Monastery; // TODO: Verify
|
||||
case eLevelId.Act1_Andariel:
|
||||
return BGMAct1AndarielAction;
|
||||
case eLevelId.Act1_Tristram:
|
||||
return BGMAct1Tristram;
|
||||
case eLevelId.Act2_Town:
|
||||
return BGMAct2Town2;
|
||||
case eLevelId.Act2_Harem:
|
||||
return BGMAct2Harem;
|
||||
case eLevelId.Act2_DurielsLair:
|
||||
return BGMAct2Lair;
|
||||
case eLevelId.Act3_Town:
|
||||
return BGMAct3Town3;
|
||||
case eLevelId.Act3_DungeonTreasure1:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_DungeonTreasure2:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_SewerTreasureX:
|
||||
return BGMAct3KurastSewer; // TODO: Verify
|
||||
case eLevelId.Act3_Temple1:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_Temple2:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_Temple3:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_Temple4:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_Temple5:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_Temple6:
|
||||
return BGMAct3Kurast; // TODO: Verify
|
||||
case eLevelId.Act3_MephistoComplex:
|
||||
return BGMAct3MefDeathAction; // TODO: Verify
|
||||
case eLevelId.Act4_Fortress:
|
||||
return BGMAct4Mesa; // TODO: Verify
|
||||
case eLevelId.Act5_Town:
|
||||
return BGMAct5XTown;
|
||||
case eLevelId.Act5_TempleFinalRoom:
|
||||
return BGMAct2Sanctuary; // TODO: Verify
|
||||
case eLevelId.Act5_ThroneRoom:
|
||||
return BGMAct2Sanctuary; // TODO: Verify
|
||||
case eLevelId.Act5_WorldStone:
|
||||
return BGMAct4ForgeAction; // TODO: Verify
|
||||
case eLevelId.Act5_TempleEntrance:
|
||||
return BGMAct5Baal; // TODO: Verify
|
||||
case eLevelId.Act5_BaalEntrance:
|
||||
return BGMAct5Baal; // TODO: Verify
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetHeroSkillPanel(eHero hero)
|
||||
{
|
||||
switch (hero)
|
||||
{
|
||||
case eHero.Amazon:
|
||||
return SkillsPanelAmazon;
|
||||
case eHero.Assassin:
|
||||
return SkillsPanelAssassin;
|
||||
case eHero.Barbarian:
|
||||
return SkillsPanelBarbarian;
|
||||
case eHero.Druid:
|
||||
return SkillsPanelDruid;
|
||||
case eHero.Necromancer:
|
||||
return SkillsPanelNecromancer;
|
||||
case eHero.Paladin:
|
||||
return SkillsPanelPaladin;
|
||||
case eHero.Sorceress:
|
||||
return SkillsPanelSorcerer;
|
||||
default:
|
||||
throw new ArgumentException($"Unknown hero type: {hero}");
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetHeroSkillsIcons(eHero hero)
|
||||
{
|
||||
switch (hero)
|
||||
{
|
||||
case eHero.None:
|
||||
return GenericSkills;
|
||||
case eHero.Amazon:
|
||||
return AmazonSkills;
|
||||
case eHero.Assassin:
|
||||
return AssassinSkills;
|
||||
case eHero.Barbarian:
|
||||
return BarbarianSkills;
|
||||
case eHero.Druid:
|
||||
return DruidSkills;
|
||||
case eHero.Necromancer:
|
||||
return NecromancerSkills;
|
||||
case eHero.Paladin:
|
||||
return PaladinSkills;
|
||||
case eHero.Sorceress:
|
||||
return SorcererSkills;
|
||||
default:
|
||||
throw new ArgumentException($"Unknown hero type: {hero}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace OpenDiablo2.Core
|
|||
public ImmutableDictionary<eHero, ILevelExperienceConfig> ExperienceConfigs { get; internal set; }
|
||||
public ImmutableDictionary<eHero, IHeroTypeConfig> HeroTypeConfigs { get; internal set; }
|
||||
public ImmutableList<IEnemyTypeConfig> EnemyTypeConfigs { get; internal set; }
|
||||
public ImmutableDictionary<int, IMissileTypeConfig> MissileTypeConfigs { get; internal set; }
|
||||
|
||||
public EngineDataManager(IMPQProvider mpqProvider)
|
||||
{
|
||||
|
@ -37,6 +38,7 @@ namespace OpenDiablo2.Core
|
|||
LoadLevelDetails();
|
||||
LoadCharacterData();
|
||||
LoadEnemyData();
|
||||
LoadSkillData();
|
||||
|
||||
Items = LoadItemData();
|
||||
}
|
||||
|
@ -50,7 +52,7 @@ namespace OpenDiablo2.Core
|
|||
.Skip(1)
|
||||
.Where(x => !String.IsNullOrWhiteSpace(x))
|
||||
.Select(x => x.Split('\t'))
|
||||
.Where(x => x.Count() == 36 && x[0] != "Expansion")
|
||||
.Where(x => x.Count() >= 36 && x[0] != "Expansion")
|
||||
.Select(x => x.ToLevelType())
|
||||
.ToImmutableList();
|
||||
|
||||
|
@ -61,7 +63,7 @@ namespace OpenDiablo2.Core
|
|||
.Skip(1)
|
||||
.Where(x => !String.IsNullOrWhiteSpace(x))
|
||||
.Select(x => x.Split('\t'))
|
||||
.Where(x => x.Count() == 24 && x[0] != "Expansion")
|
||||
.Where(x => x.Count() >= 24 && x[0] != "Expansion")
|
||||
.Select(x => x.ToLevelPreset())
|
||||
.ToImmutableList();
|
||||
|
||||
|
@ -170,7 +172,8 @@ namespace OpenDiablo2.Core
|
|||
|
||||
private void LoadEnemyData()
|
||||
{
|
||||
EnemyTypeConfigs = LoadEnemyTypeConfig();
|
||||
//TODO: RE-ENABLE THIS once monstats is being loaded properly
|
||||
//EnemyTypeConfigs = LoadEnemyTypeConfig();
|
||||
}
|
||||
|
||||
private ImmutableList<IEnemyTypeConfig> LoadEnemyTypeConfig()
|
||||
|
@ -183,5 +186,26 @@ namespace OpenDiablo2.Core
|
|||
.ToArray()
|
||||
.Select(x => x.ToEnemyTypeConfig())
|
||||
.ToImmutableList();
|
||||
|
||||
private void LoadSkillData()
|
||||
{
|
||||
MissileTypeConfigs = LoadMissileTypeConfig();
|
||||
}
|
||||
|
||||
private ImmutableDictionary<int, IMissileTypeConfig> LoadMissileTypeConfig()
|
||||
{
|
||||
var data = mpqProvider
|
||||
.GetTextFile(ResourcePaths.Missiles)
|
||||
.Where(x => !String.IsNullOrWhiteSpace(x));
|
||||
|
||||
var splitdata = data
|
||||
.Select(x => x.Split('\t'))
|
||||
.Where(x => x[0] != "Expansion" && x[0] != "unused")
|
||||
.ToArray();
|
||||
|
||||
// TODO: UNFINISHED
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace OpenDiablo2.Core.GameState_
|
|||
public string MapName { get; private set; }
|
||||
public Palette CurrentPalette => paletteProvider.PaletteTable[$"ACT{Act}"];
|
||||
public List<PlayerInfo> PlayerInfos { get; private set; }
|
||||
public eDifficulty Difficulty { get; private set; }
|
||||
|
||||
readonly private IMouseCursor originalMouseCursor;
|
||||
|
||||
|
@ -78,7 +79,7 @@ namespace OpenDiablo2.Core.GameState_
|
|||
mapDataLookup = new List<MapCellInfo>();
|
||||
}
|
||||
|
||||
public void Initialize(string characterName, eHero hero, eSessionType sessionType)
|
||||
public void Initialize(string characterName, eHero hero, eSessionType sessionType, eDifficulty difficulty)
|
||||
{
|
||||
sessionManager = getSessionManager(sessionType);
|
||||
sessionManager.Initialize();
|
||||
|
@ -88,6 +89,8 @@ namespace OpenDiablo2.Core.GameState_
|
|||
sessionManager.OnPlayerInfo += OnPlayerInfo;
|
||||
sessionManager.OnFocusOnPlayer += OnFocusOnPlayer;
|
||||
|
||||
Difficulty = difficulty;
|
||||
|
||||
mapInfo = new List<IMapInfo>();
|
||||
|
||||
sceneManager.ChangeScene(eSceneType.Game);
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace OpenDiablo2.Core
|
|||
.EnumerateFiles(globalConfiguration.BaseDataPath, "*.mpq")
|
||||
.Where(x => !(Path.GetFileName(x)?.StartsWith("patch") ?? false))
|
||||
.Select(file => new MPQ(file))
|
||||
.ToArray();
|
||||
.ToList();
|
||||
|
||||
|
||||
if (!_mpqs.Any())
|
||||
|
@ -74,6 +74,32 @@ namespace OpenDiablo2.Core
|
|||
foreach (var file in _mpqs[i].Files)
|
||||
_mpqLookup[file.ToLower()] = i;
|
||||
}
|
||||
|
||||
// Get the combined list file by joining all of the other mpqs
|
||||
List<string> superListFile = _mpqs.SelectMany(x => x.Files).ToList();
|
||||
|
||||
var patchMPQ = Directory
|
||||
.EnumerateFiles(globalConfiguration.BaseDataPath, "*.mpq")
|
||||
.Where(x => Path.GetFileName(x).StartsWith("patch"))
|
||||
.Select(file => new MPQ(file, superListFile))
|
||||
.First();
|
||||
|
||||
_mpqs.Add(patchMPQ);
|
||||
int patchMPQIndex = _mpqs.Count - 1;
|
||||
|
||||
// Replace existing mpqLookups with those from the patch, which take precedence
|
||||
foreach (var file in patchMPQ.Files)
|
||||
{
|
||||
// unlike the other mpqs, we need to ensure that the files actually exist
|
||||
// inside of the patch mpq instead of assuming that they do, because
|
||||
// we can't trust the filelist
|
||||
if (!patchMPQ.HasFile(file))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_mpqLookup[file.ToLower()] = patchMPQIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] GetBytes(string fileName)
|
||||
|
|
|
@ -1,234 +1,234 @@
|
|||
using OpenDiablo2.Common;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
using OpenDiablo2.Common.Models;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenDiablo2.Core.UI
|
||||
{
|
||||
public sealed class Button : IButton
|
||||
{
|
||||
private readonly IMouseInfoProvider mouseInfoProvider;
|
||||
private readonly IRenderWindow renderWindow;
|
||||
private readonly ISoundProvider musicProvider;
|
||||
private readonly ButtonLayout buttonLayout;
|
||||
private readonly byte[] sfxButtonClick;
|
||||
|
||||
public OnActivateDelegate OnActivate { get; set; }
|
||||
public OnToggleDelegate OnToggle { get; set; }
|
||||
|
||||
private Point location = new Point();
|
||||
public Point Location
|
||||
{
|
||||
get => location;
|
||||
set
|
||||
{
|
||||
location = value;
|
||||
sprite.Location = value;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly int buttonWidth;
|
||||
private readonly int buttonHeight;
|
||||
private readonly ISprite sprite;
|
||||
private readonly IFont font;
|
||||
private readonly ILabel label;
|
||||
private bool pressed = false;
|
||||
private bool active = false; // When true, button is actively being focus pressed
|
||||
private bool activeLock = false; // When true, we have locked the mouse from everything else
|
||||
public bool Toggled { get; private set; } = false;
|
||||
|
||||
private Point labelOffset = new Point();
|
||||
|
||||
private bool enabled = true;
|
||||
public bool Enabled
|
||||
{
|
||||
get => enabled;
|
||||
set
|
||||
{
|
||||
if (value == enabled)
|
||||
return;
|
||||
enabled = value;
|
||||
|
||||
if(buttonLayout.IsDarkenedWhenDisabled)
|
||||
sprite.Darken = !enabled;
|
||||
}
|
||||
}
|
||||
|
||||
private string text;
|
||||
public string Text
|
||||
{
|
||||
get => text;
|
||||
set
|
||||
{
|
||||
text = value;
|
||||
UpdateText();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Button(
|
||||
ButtonLayout buttonLayout,
|
||||
IRenderWindow renderWindow,
|
||||
IMouseInfoProvider mouseInfoProvider,
|
||||
ISoundProvider soundProvider,
|
||||
IMPQProvider mpqProvider
|
||||
)
|
||||
{
|
||||
this.buttonLayout = buttonLayout;
|
||||
this.renderWindow = renderWindow;
|
||||
this.mouseInfoProvider = mouseInfoProvider;
|
||||
this.musicProvider = soundProvider;
|
||||
|
||||
font = renderWindow.LoadFont(buttonLayout.FontPath, Palettes.Units);
|
||||
label = renderWindow.CreateLabel(font);
|
||||
|
||||
sprite = renderWindow.LoadSprite(buttonLayout.ResourceName, buttonLayout.PaletteName, true);
|
||||
|
||||
// TODO: Less stupid way of doing this would be super nice
|
||||
buttonWidth = 0;
|
||||
buttonHeight = 0;
|
||||
for (int i = 0; i < buttonLayout.XSegments; i++)
|
||||
{
|
||||
sprite.Frame = i;
|
||||
buttonWidth += sprite.LocalFrameSize.Width;
|
||||
}
|
||||
for(int i = 0; i < buttonLayout.YSegments; i++)
|
||||
{
|
||||
sprite.Frame = i * buttonLayout.YSegments;
|
||||
buttonHeight += sprite.LocalFrameSize.Height;
|
||||
}
|
||||
|
||||
label.MaxWidth = buttonWidth - 8;
|
||||
label.Alignment = Common.Enums.eTextAlign.Centered;
|
||||
|
||||
sfxButtonClick = mpqProvider.GetBytes(ResourcePaths.SFXButtonClick);
|
||||
}
|
||||
|
||||
public bool Toggle()
|
||||
{
|
||||
Toggled = !Toggled;
|
||||
|
||||
OnToggle?.Invoke(Toggled);
|
||||
|
||||
return Toggled;
|
||||
}
|
||||
|
||||
public bool Toggle(bool isToggled)
|
||||
{
|
||||
if(Toggled != isToggled)
|
||||
{
|
||||
OnToggle?.Invoke(isToggled);
|
||||
|
||||
Toggled = isToggled;
|
||||
}
|
||||
|
||||
return isToggled;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (!enabled)
|
||||
{
|
||||
// Prevent sticky locks
|
||||
if (activeLock && mouseInfoProvider.ReserveMouse)
|
||||
{
|
||||
activeLock = false;
|
||||
mouseInfoProvider.ReserveMouse = false;
|
||||
}
|
||||
|
||||
active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
int clickWidth = buttonLayout.ClickableRect.Width > 0 ? buttonLayout.ClickableRect.Width : buttonWidth;
|
||||
int clickHeight = buttonLayout.ClickableRect.Height > 0 ? buttonLayout.ClickableRect.Height : buttonHeight;
|
||||
|
||||
var hovered = mouseInfoProvider.MouseX >= location.X + buttonLayout.ClickableRect.X
|
||||
&& mouseInfoProvider.MouseY >= location.Y + buttonLayout.ClickableRect.Y
|
||||
&& mouseInfoProvider.MouseX < location.X + clickWidth + buttonLayout.ClickableRect.X
|
||||
&& mouseInfoProvider.MouseY < location.Y + clickHeight + buttonLayout.ClickableRect.Y;
|
||||
|
||||
if (!activeLock && hovered && mouseInfoProvider.LeftMouseDown && !mouseInfoProvider.ReserveMouse)
|
||||
{
|
||||
// The button is being pressed down
|
||||
mouseInfoProvider.ReserveMouse = true;
|
||||
active = true;
|
||||
musicProvider.PlaySfx(sfxButtonClick);
|
||||
}
|
||||
else if (active && !mouseInfoProvider.LeftMouseDown)
|
||||
{
|
||||
mouseInfoProvider.ReserveMouse = false;
|
||||
active = false;
|
||||
|
||||
if (hovered)
|
||||
{
|
||||
OnActivate?.Invoke();
|
||||
|
||||
if (buttonLayout.Toggleable)
|
||||
{
|
||||
Toggle();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (!active && mouseInfoProvider.LeftMouseDown)
|
||||
{
|
||||
activeLock = true;
|
||||
}
|
||||
else if (activeLock && !mouseInfoProvider.LeftMouseDown)
|
||||
{
|
||||
activeLock = false;
|
||||
}
|
||||
|
||||
pressed = hovered && mouseInfoProvider.LeftMouseDown && active;
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
var frame = buttonLayout.BaseFrame;
|
||||
|
||||
if (buttonLayout.AllowFrameChange)
|
||||
{
|
||||
if(!Enabled && buttonLayout.DisabledFrame >= 0)
|
||||
{
|
||||
frame = buttonLayout.DisabledFrame;
|
||||
}
|
||||
else if (Toggled && pressed)
|
||||
{
|
||||
frame = buttonLayout.BaseFrame + 3;
|
||||
}
|
||||
else if (pressed)
|
||||
{
|
||||
frame = buttonLayout.BaseFrame + 1;
|
||||
}
|
||||
else if (Toggled)
|
||||
{
|
||||
frame = buttonLayout.BaseFrame + 2;
|
||||
}
|
||||
}
|
||||
|
||||
renderWindow.Draw(sprite, buttonLayout.XSegments, buttonLayout.YSegments, frame);
|
||||
var offset = pressed ? -2 : 0;
|
||||
|
||||
label.Location = new Point(location.X + offset + labelOffset.X, location.Y - offset + labelOffset.Y);
|
||||
renderWindow.Draw(label);
|
||||
}
|
||||
|
||||
private void UpdateText()
|
||||
{
|
||||
label.Text = text;
|
||||
label.TextColor = Color.FromArgb(75, 75, 75);
|
||||
|
||||
var offsetX = (buttonWidth / 2) - (label.TextArea.Width / 2);
|
||||
var offsetY = (buttonHeight / 2) - (label.TextArea.Height / 2);
|
||||
labelOffset = new Point(offsetX, offsetY - 5);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
sprite.Dispose();
|
||||
font.Dispose();
|
||||
label.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
using OpenDiablo2.Common;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
using OpenDiablo2.Common.Models;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenDiablo2.Core.UI
|
||||
{
|
||||
public sealed class Button : IButton
|
||||
{
|
||||
private readonly IMouseInfoProvider mouseInfoProvider;
|
||||
private readonly IRenderWindow renderWindow;
|
||||
private readonly ISoundProvider musicProvider;
|
||||
private readonly ButtonLayout buttonLayout;
|
||||
private readonly byte[] sfxButtonClick;
|
||||
|
||||
public OnActivateDelegate OnActivate { get; set; }
|
||||
public OnToggleDelegate OnToggle { get; set; }
|
||||
|
||||
private Point location = new Point();
|
||||
public Point Location
|
||||
{
|
||||
get => location;
|
||||
set
|
||||
{
|
||||
location = value;
|
||||
sprite.Location = value;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly int buttonWidth;
|
||||
private readonly int buttonHeight;
|
||||
private readonly ISprite sprite;
|
||||
private readonly IFont font;
|
||||
private readonly ILabel label;
|
||||
private bool pressed = false;
|
||||
private bool active = false; // When true, button is actively being focus pressed
|
||||
private bool activeLock = false; // When true, we have locked the mouse from everything else
|
||||
public bool Toggled { get; private set; } = false;
|
||||
|
||||
private Point labelOffset = new Point();
|
||||
|
||||
private bool enabled = true;
|
||||
public bool Enabled
|
||||
{
|
||||
get => enabled;
|
||||
set
|
||||
{
|
||||
if (value == enabled)
|
||||
return;
|
||||
enabled = value;
|
||||
|
||||
if(buttonLayout.IsDarkenedWhenDisabled)
|
||||
sprite.Darken = !enabled;
|
||||
}
|
||||
}
|
||||
|
||||
private string text;
|
||||
public string Text
|
||||
{
|
||||
get => text;
|
||||
set
|
||||
{
|
||||
text = value;
|
||||
UpdateText();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Button(
|
||||
ButtonLayout buttonLayout,
|
||||
IRenderWindow renderWindow,
|
||||
IMouseInfoProvider mouseInfoProvider,
|
||||
ISoundProvider soundProvider,
|
||||
IMPQProvider mpqProvider
|
||||
)
|
||||
{
|
||||
this.buttonLayout = buttonLayout;
|
||||
this.renderWindow = renderWindow;
|
||||
this.mouseInfoProvider = mouseInfoProvider;
|
||||
this.musicProvider = soundProvider;
|
||||
|
||||
font = renderWindow.LoadFont(buttonLayout.FontPath, Palettes.Units);
|
||||
label = renderWindow.CreateLabel(font);
|
||||
|
||||
sprite = renderWindow.LoadSprite(buttonLayout.ResourceName, buttonLayout.PaletteName, true);
|
||||
|
||||
// TODO: Less stupid way of doing this would be super nice
|
||||
buttonWidth = 0;
|
||||
buttonHeight = 0;
|
||||
for (int i = 0; i < buttonLayout.XSegments; i++)
|
||||
{
|
||||
sprite.Frame = i;
|
||||
buttonWidth += sprite.LocalFrameSize.Width;
|
||||
}
|
||||
for(int i = 0; i < buttonLayout.YSegments; i++)
|
||||
{
|
||||
sprite.Frame = i * buttonLayout.YSegments;
|
||||
buttonHeight += sprite.LocalFrameSize.Height;
|
||||
}
|
||||
|
||||
label.MaxWidth = buttonWidth - 8;
|
||||
label.Alignment = Common.Enums.eTextAlign.Centered;
|
||||
|
||||
sfxButtonClick = mpqProvider.GetBytes(ResourcePaths.SFXButtonClick);
|
||||
}
|
||||
|
||||
public bool Toggle()
|
||||
{
|
||||
Toggled = !Toggled;
|
||||
|
||||
OnToggle?.Invoke(Toggled);
|
||||
|
||||
return Toggled;
|
||||
}
|
||||
|
||||
public bool Toggle(bool isToggled)
|
||||
{
|
||||
if(Toggled != isToggled)
|
||||
{
|
||||
OnToggle?.Invoke(isToggled);
|
||||
|
||||
Toggled = isToggled;
|
||||
}
|
||||
|
||||
return isToggled;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (!enabled)
|
||||
{
|
||||
// Prevent sticky locks
|
||||
if (activeLock && mouseInfoProvider.ReserveMouse)
|
||||
{
|
||||
activeLock = false;
|
||||
mouseInfoProvider.ReserveMouse = false;
|
||||
}
|
||||
|
||||
active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
int clickWidth = buttonLayout.ClickableRect.Width > 0 ? buttonLayout.ClickableRect.Width : buttonWidth;
|
||||
int clickHeight = buttonLayout.ClickableRect.Height > 0 ? buttonLayout.ClickableRect.Height : buttonHeight;
|
||||
|
||||
var hovered = mouseInfoProvider.MouseX >= location.X + buttonLayout.ClickableRect.X
|
||||
&& mouseInfoProvider.MouseY >= location.Y + buttonLayout.ClickableRect.Y
|
||||
&& mouseInfoProvider.MouseX < location.X + clickWidth + buttonLayout.ClickableRect.X
|
||||
&& mouseInfoProvider.MouseY < location.Y + clickHeight + buttonLayout.ClickableRect.Y;
|
||||
|
||||
if (!activeLock && hovered && mouseInfoProvider.LeftMouseDown && !mouseInfoProvider.ReserveMouse)
|
||||
{
|
||||
// The button is being pressed down
|
||||
mouseInfoProvider.ReserveMouse = true;
|
||||
active = true;
|
||||
musicProvider.PlaySfx(sfxButtonClick);
|
||||
}
|
||||
else if (active && !mouseInfoProvider.LeftMouseDown)
|
||||
{
|
||||
mouseInfoProvider.ReserveMouse = false;
|
||||
active = false;
|
||||
|
||||
if (hovered)
|
||||
{
|
||||
OnActivate?.Invoke();
|
||||
|
||||
if (buttonLayout.Toggleable)
|
||||
{
|
||||
Toggle();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (!active && mouseInfoProvider.LeftMouseDown)
|
||||
{
|
||||
activeLock = true;
|
||||
}
|
||||
else if (activeLock && !mouseInfoProvider.LeftMouseDown)
|
||||
{
|
||||
activeLock = false;
|
||||
}
|
||||
|
||||
pressed = hovered && mouseInfoProvider.LeftMouseDown && active;
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
var frame = buttonLayout.BaseFrame;
|
||||
|
||||
if (buttonLayout.AllowFrameChange)
|
||||
{
|
||||
if(!Enabled && buttonLayout.DisabledFrame >= 0)
|
||||
{
|
||||
frame = buttonLayout.DisabledFrame;
|
||||
}
|
||||
else if (Toggled && pressed)
|
||||
{
|
||||
frame = buttonLayout.BaseFrame + 3;
|
||||
}
|
||||
else if (pressed)
|
||||
{
|
||||
frame = buttonLayout.BaseFrame + 1;
|
||||
}
|
||||
else if (Toggled)
|
||||
{
|
||||
frame = buttonLayout.BaseFrame + 2;
|
||||
}
|
||||
}
|
||||
|
||||
renderWindow.Draw(sprite, buttonLayout.XSegments, buttonLayout.YSegments, frame);
|
||||
var offset = pressed ? -2 : 0;
|
||||
|
||||
label.Location = new Point(location.X + offset + labelOffset.X, location.Y - offset + labelOffset.Y);
|
||||
renderWindow.Draw(label);
|
||||
}
|
||||
|
||||
private void UpdateText()
|
||||
{
|
||||
label.Text = text;
|
||||
label.TextColor = Color.FromArgb(75, 75, 75);
|
||||
|
||||
var offsetX = (buttonWidth / 2) - (label.TextArea.Width / 2);
|
||||
var offsetY = (buttonHeight / 2) - (label.TextArea.Height / 2);
|
||||
labelOffset = new Point(offsetX, offsetY - 5);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
sprite.Dispose();
|
||||
font.Dispose();
|
||||
label.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,10 +14,12 @@ namespace OpenDiablo2.MapGenerators
|
|||
private readonly IGameState gameState;
|
||||
|
||||
private readonly LevelDetail levelDetail;
|
||||
private readonly eDifficulty difficulty;
|
||||
|
||||
public BloodMoor(IGameState gameState, IEngineDataManager dataManager)
|
||||
{
|
||||
this.gameState = gameState;
|
||||
this.difficulty = gameState.Difficulty;
|
||||
|
||||
levelDetail = dataManager.Levels.First(x => x.LevelName == "Blood Moor");
|
||||
}
|
||||
|
@ -192,8 +194,8 @@ namespace OpenDiablo2.MapGenerators
|
|||
// Generate the cave
|
||||
while (true)
|
||||
{
|
||||
var rx = random.Next(8, levelDetail.SizeX - 16);
|
||||
var ry = random.Next(8, levelDetail.SizeY - 16);
|
||||
var rx = random.Next(8, levelDetail.Difficulties[difficulty].SizeX - 16);
|
||||
var ry = random.Next(8, levelDetail.Difficulties[difficulty].SizeY - 16);
|
||||
rx -= (rx % 8);
|
||||
ry -= (ry % 8);
|
||||
var caveX = rx + location.X;
|
||||
|
@ -215,8 +217,8 @@ namespace OpenDiablo2.MapGenerators
|
|||
var campsToGenerate = 3;
|
||||
while (campsToGenerate > 0)
|
||||
{
|
||||
var rx = random.Next(8, levelDetail.SizeX - 16);
|
||||
var ry = random.Next(8, levelDetail.SizeY - 16);
|
||||
var rx = random.Next(8, levelDetail.Difficulties[difficulty].SizeX - 16);
|
||||
var ry = random.Next(8, levelDetail.Difficulties[difficulty].SizeY - 16);
|
||||
rx -= (rx % 8);
|
||||
ry -= (ry % 8);
|
||||
var campX = rx + location.X;
|
||||
|
@ -243,8 +245,8 @@ namespace OpenDiablo2.MapGenerators
|
|||
static int[] tileFillIds = new int[] { 29, 30, 31, 38, 39, 40, 41 };
|
||||
private void FillCenterArea(Point location, IMapInfo parentMap)
|
||||
{
|
||||
var rightEdge = levelDetail.SizeX - 8;
|
||||
var bottomEdge = levelDetail.SizeY - 8;
|
||||
var rightEdge = levelDetail.Difficulties[difficulty].SizeX - 8;
|
||||
var bottomEdge = levelDetail.Difficulties[difficulty].SizeY - 8;
|
||||
|
||||
for (var y = 8; y < bottomEdge; y += 8)
|
||||
{
|
||||
|
|
|
@ -1,122 +1,122 @@
|
|||
/* 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;
|
||||
using OpenDiablo2.Common.Attributes;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
using System;
|
||||
|
||||
namespace OpenDiablo2.Scenes
|
||||
{
|
||||
[Scene(eSceneType.Game)]
|
||||
public sealed class Game : IScene
|
||||
{
|
||||
private readonly IRenderWindow renderWindow;
|
||||
private readonly IMapEngine mapEngine;
|
||||
private readonly IMouseInfoProvider mouseInfoProvider;
|
||||
private readonly IGameState gameState;
|
||||
private readonly ISessionManager sessionManager;
|
||||
private readonly IGameHUD gameHUD;
|
||||
|
||||
private eMovementType lastMovementType = eMovementType.Stopped;
|
||||
private byte lastDirection = 255;
|
||||
private bool clickedOnHud = false;
|
||||
|
||||
const double Rad2Deg = 180.0 / Math.PI;
|
||||
|
||||
public Game(
|
||||
IRenderWindow renderWindow,
|
||||
IMapEngine mapEngine,
|
||||
IGameState gameState,
|
||||
IMouseInfoProvider mouseInfoProvider,
|
||||
IItemManager itemManager,
|
||||
ISessionManager sessionManager,
|
||||
ISoundProvider soundProvider,
|
||||
IMPQProvider mpqProvider,
|
||||
IGameHUD gameHUD
|
||||
)
|
||||
{
|
||||
this.renderWindow = renderWindow;
|
||||
this.mapEngine = mapEngine;
|
||||
this.gameState = gameState;
|
||||
this.mouseInfoProvider = mouseInfoProvider;
|
||||
this.sessionManager = sessionManager;
|
||||
this.gameHUD = gameHUD;
|
||||
|
||||
//var item = itemManager.getItem("hdm");
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
// TODO: Maybe show some sort of connecting/loading message?
|
||||
if (mapEngine.FocusedPlayerId == 0)
|
||||
return;
|
||||
|
||||
mapEngine.Render();
|
||||
gameHUD.Render();
|
||||
}
|
||||
|
||||
public void Update(long ms)
|
||||
{
|
||||
HandleMovement();
|
||||
|
||||
mapEngine.Update(ms);
|
||||
gameHUD.Update();
|
||||
}
|
||||
|
||||
private void HandleMovement()
|
||||
{
|
||||
if(gameHUD.IsMouseOver() && lastMovementType == eMovementType.Stopped)
|
||||
clickedOnHud = true;
|
||||
else if (!mouseInfoProvider.LeftMouseDown)
|
||||
clickedOnHud = false;
|
||||
|
||||
if (clickedOnHud)
|
||||
return;
|
||||
|
||||
var mx = mouseInfoProvider.MouseX - 400 - gameState.CameraOffset;
|
||||
var my = mouseInfoProvider.MouseY - 300;
|
||||
|
||||
var tx = (mx / 60f + my / 40f) / 2f;
|
||||
var ty = (my / 40f - (mx / 60f)) / 2f;
|
||||
var cursorDirection = (int)Math.Round(Math.Atan2(ty, tx) * Rad2Deg);
|
||||
if (cursorDirection < 0)
|
||||
cursorDirection += 360;
|
||||
var actualDirection = (byte)(cursorDirection / 22);
|
||||
if (actualDirection >= 16)
|
||||
actualDirection -= 16;
|
||||
|
||||
if (mouseInfoProvider.LeftMouseDown && (lastMovementType == eMovementType.Stopped || lastDirection != actualDirection))
|
||||
{
|
||||
lastDirection = actualDirection;
|
||||
lastMovementType = gameHUD.IsRunningEnabled ? eMovementType.Running : eMovementType.Walking;
|
||||
sessionManager.MoveRequest(actualDirection, lastMovementType);
|
||||
}
|
||||
else if (!mouseInfoProvider.LeftMouseDown && lastMovementType != eMovementType.Stopped)
|
||||
{
|
||||
lastDirection = actualDirection;
|
||||
lastMovementType = eMovementType.Stopped;
|
||||
sessionManager.MoveRequest(actualDirection, lastMovementType);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 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;
|
||||
using OpenDiablo2.Common.Attributes;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
using System;
|
||||
|
||||
namespace OpenDiablo2.Scenes
|
||||
{
|
||||
[Scene(eSceneType.Game)]
|
||||
public sealed class Game : IScene
|
||||
{
|
||||
private readonly IRenderWindow renderWindow;
|
||||
private readonly IMapEngine mapEngine;
|
||||
private readonly IMouseInfoProvider mouseInfoProvider;
|
||||
private readonly IGameState gameState;
|
||||
private readonly ISessionManager sessionManager;
|
||||
private readonly IGameHUD gameHUD;
|
||||
|
||||
private eMovementType lastMovementType = eMovementType.Stopped;
|
||||
private byte lastDirection = 255;
|
||||
private bool clickedOnHud = false;
|
||||
|
||||
const double Rad2Deg = 180.0 / Math.PI;
|
||||
|
||||
public Game(
|
||||
IRenderWindow renderWindow,
|
||||
IMapEngine mapEngine,
|
||||
IGameState gameState,
|
||||
IMouseInfoProvider mouseInfoProvider,
|
||||
IItemManager itemManager,
|
||||
ISessionManager sessionManager,
|
||||
ISoundProvider soundProvider,
|
||||
IMPQProvider mpqProvider,
|
||||
IGameHUD gameHUD
|
||||
)
|
||||
{
|
||||
this.renderWindow = renderWindow;
|
||||
this.mapEngine = mapEngine;
|
||||
this.gameState = gameState;
|
||||
this.mouseInfoProvider = mouseInfoProvider;
|
||||
this.sessionManager = sessionManager;
|
||||
this.gameHUD = gameHUD;
|
||||
|
||||
//var item = itemManager.getItem("hdm");
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
// TODO: Maybe show some sort of connecting/loading message?
|
||||
if (mapEngine.FocusedPlayerId == 0)
|
||||
return;
|
||||
|
||||
mapEngine.Render();
|
||||
gameHUD.Render();
|
||||
}
|
||||
|
||||
public void Update(long ms)
|
||||
{
|
||||
HandleMovement();
|
||||
|
||||
mapEngine.Update(ms);
|
||||
gameHUD.Update();
|
||||
}
|
||||
|
||||
private void HandleMovement()
|
||||
{
|
||||
if(gameHUD.IsMouseOver() && lastMovementType == eMovementType.Stopped)
|
||||
clickedOnHud = true;
|
||||
else if (!mouseInfoProvider.LeftMouseDown)
|
||||
clickedOnHud = false;
|
||||
|
||||
if (clickedOnHud)
|
||||
return;
|
||||
|
||||
var mx = mouseInfoProvider.MouseX - 400 - gameState.CameraOffset;
|
||||
var my = mouseInfoProvider.MouseY - 300;
|
||||
|
||||
var tx = (mx / 60f + my / 40f) / 2f;
|
||||
var ty = (my / 40f - (mx / 60f)) / 2f;
|
||||
var cursorDirection = (int)Math.Round(Math.Atan2(ty, tx) * Rad2Deg);
|
||||
if (cursorDirection < 0)
|
||||
cursorDirection += 360;
|
||||
var actualDirection = (byte)(cursorDirection / 22);
|
||||
if (actualDirection >= 16)
|
||||
actualDirection -= 16;
|
||||
|
||||
if (mouseInfoProvider.LeftMouseDown && (lastMovementType == eMovementType.Stopped || lastDirection != actualDirection))
|
||||
{
|
||||
lastDirection = actualDirection;
|
||||
lastMovementType = gameHUD.IsRunningEnabled ? eMovementType.Running : eMovementType.Walking;
|
||||
sessionManager.MoveRequest(actualDirection, lastMovementType);
|
||||
}
|
||||
else if (!mouseInfoProvider.LeftMouseDown && lastMovementType != eMovementType.Stopped)
|
||||
{
|
||||
lastDirection = actualDirection;
|
||||
lastMovementType = eMovementType.Stopped;
|
||||
sessionManager.MoveRequest(actualDirection, lastMovementType);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -271,7 +271,8 @@ namespace OpenDiablo2.Scenes
|
|||
StopSfx();
|
||||
|
||||
// TODO: Support other session types
|
||||
gameState.Initialize(characterNameTextBox.Text, selectedHero.Value, eSessionType.Local);
|
||||
// TODO: support other difficulty types
|
||||
gameState.Initialize(characterNameTextBox.Text, selectedHero.Value, eSessionType.Local, eDifficulty.NORMAL);
|
||||
}
|
||||
|
||||
private void OnExitClicked()
|
||||
|
@ -321,7 +322,7 @@ namespace OpenDiablo2.Scenes
|
|||
|
||||
private void RenderHeros()
|
||||
{
|
||||
var heros = Enum.GetValues(typeof(eHero)).Cast<eHero>();
|
||||
var heros = Enum.GetValues(typeof(eHero)).Cast<eHero>().Skip(1); // skip NONE
|
||||
foreach (var hero in heros)
|
||||
if (heroRenderInfo[hero].Stance == eHeroStance.Idle || heroRenderInfo[hero].Stance == eHeroStance.IdleSelected)
|
||||
RenderHero(hero);
|
||||
|
@ -419,6 +420,10 @@ namespace OpenDiablo2.Scenes
|
|||
|
||||
private void UpdateHeroSelectionHover(eHero hero, long ms, bool canSelect)
|
||||
{
|
||||
if(hero == eHero.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var renderInfo = heroRenderInfo[hero];
|
||||
if (renderInfo.Stance == eHeroStance.Approaching)
|
||||
{
|
||||
|
|
BIN
Screenshot.png
BIN
Screenshot.png
Binary file not shown.
Before Width: | Height: | Size: 521 KiB |
BIN
Screenshot2.png
BIN
Screenshot2.png
Binary file not shown.
Before Width: | Height: | Size: 728 KiB |
Loading…
Reference in New Issue
Block a user