diff --git a/src/DiIiS-NA/Core/MPQ/Data.cs b/src/DiIiS-NA/Core/MPQ/Data.cs index 35e83a2..2b46703 100644 --- a/src/DiIiS-NA/Core/MPQ/Data.cs +++ b/src/DiIiS-NA/Core/MPQ/Data.cs @@ -11,10 +11,21 @@ using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; +using DiIiS_NA.D3_GameServer.Core.Types.SNO; using Spectre.Console; namespace DiIiS_NA.Core.MPQ { + [AttributeUsage(AttributeTargets.All, AllowMultiple = false)] + public class SnoFileNameAttribute : Attribute + { + public string FileName { get; } + + public SnoFileNameAttribute(string fileName) + { + FileName = fileName; + } + } public class Data : MPQPatchChain { public Dictionary> Assets = new Dictionary>(); @@ -56,12 +67,15 @@ namespace DiIiS_NA.Core.MPQ #endregion - private static new readonly Logger Logger = LogManager.CreateLogger("DataBaseWorker"); + private new static readonly Logger Logger = LogManager.CreateLogger("MPQWorker"); public Data() //: base(0, new List { "CoreData.mpq", "ClientData.mpq" }, "/base/d3-update-base-(?.*?).mpq") - : base(0, new List { "Core.mpq", "Core1.mpq", "Core2.mpq", "Core3.mpq", "Core4.mpq" }, "/base/d3-update-base-(?.*?).mpq") - { } + : base(0, new List { "Core.mpq", "Core1.mpq", "Core2.mpq", "Core3.mpq", "Core4.mpq" }, + "/base/d3-update-base-(?.*?).mpq") + { + + } public void Init() { diff --git a/src/DiIiS-NA/Core/MPQ/Dicts.cs b/src/DiIiS-NA/Core/MPQ/Dicts.cs index f55424b..141b7b5 100644 --- a/src/DiIiS-NA/Core/MPQ/Dicts.cs +++ b/src/DiIiS-NA/Core/MPQ/Dicts.cs @@ -202,7 +202,29 @@ namespace DiIiS_NA.Core.MPQ } public static Dictionary LoadActors() { - return Enum.GetValues().Where(x => x != ActorSno.__NONE).ToDictionary(x => x.ToString().Substring(1), x => (int)x); + var dict = Enum.GetValues().Where(x => x != ActorSno.__NONE).ToDictionary(x => x.ToString().Substring(1), x => (int)x); + + // TODO: merge with LINQ above. + // this parses enum values that has SnoFileNameAttribute, in case the dict linq above didn't get a correct name + // for the actor file. + foreach (var d in Enum.GetValues()) + { + var enumType = typeof(ActorSno); + var memberInfos = + enumType.GetMember(d.ToString()); + if (memberInfos.Length == 0) + continue; + var enumValueMemberInfo = memberInfos.FirstOrDefault(m => m.DeclaringType == enumType); + if (enumValueMemberInfo == null) continue; + var valueAttributes = enumValueMemberInfo.GetCustomAttributes(typeof(SnoFileNameAttribute), false) + .Select(s=>(SnoFileNameAttribute)s) + .FirstOrDefault(); + if (valueAttributes != null) + { + dict.Add(valueAttributes.FileName, (int)d); + } + } + return dict; } public static Dictionary LoadAdventure() { diff --git a/src/DiIiS-NA/Core/MPQ/FileFormats/Actor.cs b/src/DiIiS-NA/Core/MPQ/FileFormats/ActorData.cs similarity index 98% rename from src/DiIiS-NA/Core/MPQ/FileFormats/Actor.cs rename to src/DiIiS-NA/Core/MPQ/FileFormats/ActorData.cs index 7b75311..e323364 100644 --- a/src/DiIiS-NA/Core/MPQ/FileFormats/Actor.cs +++ b/src/DiIiS-NA/Core/MPQ/FileFormats/ActorData.cs @@ -12,7 +12,7 @@ using DiIiS_NA.GameServer.Core.Types.TagMap; namespace DiIiS_NA.Core.MPQ.FileFormats { [FileFormat(SNOGroup.Actor)] - public class Actor : FileFormat + public class ActorData : FileFormat { public Header Header { get; private set; } public int Flags { get; private set; } @@ -42,7 +42,7 @@ namespace DiIiS_NA.Core.MPQ.FileFormats public string CastingNotes { get; private set; } public string VoiceOverRole { get; private set; } - public Actor(MpqFile file) + public ActorData(MpqFile file) { var stream = file.Open(); Header = new Header(stream); diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ActorsCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ActorsCommand.cs new file mode 100644 index 0000000..f3abb21 --- /dev/null +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ActorsCommand.cs @@ -0,0 +1,85 @@ +using System; +using System.Linq; +using DiIiS_NA.D3_GameServer.Core.Types.SNO; +using DiIiS_NA.LoginServer.AccountsSystem; +using DiIiS_NA.LoginServer.Battle; + +namespace DiIiS_NA.GameServer.CommandManager; + +[CommandGroup("actors", + "Actors info (does not include Players, Minions and Monsters). This is useful for testing purposes.", + Account.UserLevels.Tester)] +public class ActorsCommand : CommandGroup +{ + [Command("all", "Lists all actors.", Account.UserLevels.Tester)] + public string All(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Player is not {} player) + return "You are not in game."; + + return $"World [{player.World.SNO}]\nAll actors:" + string.Join("\n", player.World.Actors + .OrderBy(a => + { + var position = player.Position; + return a.Value.Position.DistanceSquared(ref position); + }).Select(a => + { + var position = player.Position; + var distance = a.Value.Position.DistanceSquared(ref position); + return $"[{a.Value.GetType().Name}] - {a.Value.SNO}\n" + + $" > Distance: {distance}\n" + + $" > SnoId: {(int)a.Value.SNO}"; + })); + } + + [Command("revealed", "Lists all revealed actors.", Account.UserLevels.Tester)] + public string Revealed(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Player is not {} player) + return "You are not in game."; + + return $"World [{player.World.SNO}]\nVisible actors:" + string.Join("\n", player.World.Actors + .Where(a => a.Value.IsRevealedToPlayer(player)) + .OrderBy(a => + { + var position = player.Position; + return a.Value.Position.DistanceSquared(ref position); + }).Select(a => + { + var position = player.Position; + var distance = a.Value.Position.DistanceSquared(ref position); + return $"[{a.Value.GetType().Name}] - {a.Value.SNO}\n" + + $" > Distance: {distance}\n" + + $" > SnoId: {(int)a.Value.SNO}"; + })); + } + + [Command("setoperable", "Sets all actors operable (not the wisest invention).", Account.UserLevels.Tester)] + public string Operable(string[] @params, BattleClient invokerClient) + { + if (invokerClient?.InGameClient?.Player is not {} player) + return "You are not in game."; + + if (@params is { Length: > 0 }) + { + if (!Enum.TryParse(@params[0].AsSpan(), out var actorSno)) + { + return "Invalid actor SNO."; + } + + var actor = player.World.Actors.FirstOrDefault(a => a.Value.SNO == actorSno); + if (actor.Value is null) + return "Actor not found."; + actor.Value.SetVisible(true); + actor.Value.SetUsable(true); + } + var actors = player.World.Actors.Select(s=>s.Value).ToArray(); + foreach (var actor in actors) + { + actor.SetVisible(true); + actor.SetUsable(true); + } + + return $"All {actors.Length} world actors are now operable."; + } +} \ No newline at end of file diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/OpenDoorCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/DoorsCommand.cs similarity index 96% rename from src/DiIiS-NA/D3-GameServer/CommandManager/Commands/OpenDoorCommand.cs rename to src/DiIiS-NA/D3-GameServer/CommandManager/Commands/DoorsCommand.cs index c6a75cf..e6bbce9 100644 --- a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/OpenDoorCommand.cs +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/DoorsCommand.cs @@ -5,8 +5,8 @@ using DiIiS_NA.LoginServer.AccountsSystem; namespace DiIiS_NA.GameServer.CommandManager; -[CommandGroup("doors", "Information about all doors in the vicinity. This is useful for testing purposes.. Useful for testing.", Account.UserLevels.Tester)] -public class OpenDoorCommand : CommandGroup +[CommandGroup("doors", "Information about all doors in the vicinity. This is useful for testing purposes.", Account.UserLevels.Tester)] +public class DoorsCommand : CommandGroup { [Command("all", "Activate all doors. This is useful for testing purposes.\nUsage: !open all", Account.UserLevels.Tester)] public string OpenAllDoors(string[] @params, BattleClient invokerClient) diff --git a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ModifySpeedCommand.cs b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ModifySpeedCommand.cs index 5a0f01b..8da80f1 100644 --- a/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ModifySpeedCommand.cs +++ b/src/DiIiS-NA/D3-GameServer/CommandManager/Commands/ModifySpeedCommand.cs @@ -9,7 +9,6 @@ using DiIiS_NA.GameServer.GSSystem.ActorSystem; using DiIiS_NA.GameServer.GSSystem.ObjectsSystem; using DiIiS_NA.GameServer.MessageSystem; using DiIiS_NA.LoginServer.Battle; -using Actor = DiIiS_NA.Core.MPQ.FileFormats.Actor; namespace DiIiS_NA.GameServer.CommandManager; @@ -194,7 +193,7 @@ public class ModifySpeedCommand : CommandGroup return matches.Aggregate(matches.Count >= 1 ? "Actor Matches:\n" : "No match found.", (current, match) => current + - $"[{match.SNOId:D6}] {match.Name} ({((Actor)match.Data).Type} {(((Actor)match.Data).Type == ActorType.Gizmo ? ((int)((Actor)match.Data).TagMap[ActorKeys.GizmoGroup]).ToString() : "")})\n"); + $"[{match.SNOId:D6}] {match.Name} ({((ActorData)match.Data).Type} {(((ActorData)match.Data).Type == ActorType.Gizmo ? ((int)((ActorData)match.Data).TagMap[ActorKeys.GizmoGroup]).ToString() : "")})\n"); } [Command("rope", "Allows you to search for an rope.\nUsage: lookup rope ")] diff --git a/src/DiIiS-NA/D3-GameServer/Core/Types/SNO/ActorSno.cs b/src/DiIiS-NA/D3-GameServer/Core/Types/SNO/ActorSno.cs index 14a3724..841960e 100644 --- a/src/DiIiS-NA/D3-GameServer/Core/Types/SNO/ActorSno.cs +++ b/src/DiIiS-NA/D3-GameServer/Core/Types/SNO/ActorSno.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using DiIiS_NA.Core.MPQ; namespace DiIiS_NA.D3_GameServer.Core.Types.SNO { @@ -7535,12 +7536,14 @@ namespace DiIiS_NA.D3_GameServer.Core.Types.SNO _wizard_tornado_golden = 215324, _inviscylindercollisionsmall = 215351, _wizard_waveofforce_runecrimson_shell = 215420, + [SnoFileName("a1dun_Caves_Nephalem Altar_A_Chest_03")] _a1dun_caves_nephalem_altar_a_chest_03 = 215434, _arcanumorb_model = 215444, _fallenshaman_a_unique01whipple = 215445, _wizard_waveofforce_runeobsidian_shell = 215488, _cow_gem_flippy = 215500, _wizard_waveofforce_runegolden_shell = 215511, + [SnoFileName("a1dun_Caves_Nephalem Altar_A_Chest_03_B")] _a1dun_caves_nephalem_altar_a_chest_03_b = 215512, _wizard_frostnova_critbuff_swipe = 215516, _monk_hol_stage03_ribbongeo = 215635, diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Actor.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Actor.cs index fd89313..8d1b1e3 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Actor.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Actor.cs @@ -1,7 +1,6 @@ using DiIiS_NA.Core.Logging; using DiIiS_NA.D3_GameServer.Core.Types.SNO; using DiIiS_NA.GameServer.Core.Types.Math; -using DiIiS_NA.GameServer.Core.Types.Misc; using DiIiS_NA.GameServer.Core.Types.SNO; using DiIiS_NA.GameServer.Core.Types.TagMap; using DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations; @@ -9,7 +8,6 @@ using DiIiS_NA.GameServer.GSSystem.ActorSystem.Implementations.Hirelings; using DiIiS_NA.GameServer.GSSystem.GameSystem; using DiIiS_NA.GameServer.GSSystem.GeneratorsSystem; using DiIiS_NA.GameServer.GSSystem.ItemsSystem; -using DiIiS_NA.GameServer.GSSystem.MapSystem; using DiIiS_NA.GameServer.GSSystem.ObjectsSystem; using DiIiS_NA.GameServer.GSSystem.PlayerSystem; using DiIiS_NA.GameServer.GSSystem.PowerSystem; @@ -26,8 +24,12 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; using DiIiS_NA.Core.MPQ; +using DiIiS_NA.Core.MPQ.FileFormats; using DiIiS_NA.D3_GameServer.GSSystem.GameSystem; +using Circle = DiIiS_NA.GameServer.Core.Types.Misc.Circle; using Player = DiIiS_NA.GameServer.GSSystem.PlayerSystem.Player; +using Scene = DiIiS_NA.GameServer.GSSystem.MapSystem.Scene; +using World = DiIiS_NA.GameServer.GSSystem.MapSystem.World; namespace DiIiS_NA.GameServer.GSSystem.ActorSystem { @@ -168,13 +170,8 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem /// /// The info set for actor. (erekose) /// - public DiIiS_NA.Core.MPQ.FileFormats.Actor ActorData - { - get - { - return (DiIiS_NA.Core.MPQ.FileFormats.Actor)MPQStorage.Data.Assets[SNOGroup.Actor][(int)SNO].Data; - } - } + public DiIiS_NA.Core.MPQ.FileFormats.ActorData ActorData + => (DiIiS_NA.Core.MPQ.FileFormats.ActorData)MPQStorage.Data.Assets[SNOGroup.Actor][(int)SNO].Data; /// /// The animation set for actor. @@ -235,8 +232,8 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem AffixList = new List(); - //if (tags != null && tags.ContainsKey(MarkerKeys.OnActorSpawnedScript) && tags[MarkerKeys.OnActorSpawnedScript].Id == 178440) - // this.AnimationSet = (Mooege.Common.MPQ.FileFormats.AnimSet)Mooege.Common.MPQ.MPQStorage.Data.Assets[SNOGroup.AnimSet][11849].Data; //OminNPC_Male (Wounded) + // if (tags != null && tags.ContainsKey(MarkerKeys.OnActorSpawnedScript) && tags[MarkerKeys.OnActorSpawnedScript].Id == 178440) + // AnimationSet = (AnimSet)MPQStorage.Data.Assets[SNOGroup.AnimSet][11849].Data; //OminNPC_Male (Wounded) //else // if (this.ActorData.AnimSetSNO != -1) // this.AnimationSet = (Mooege.Common.MPQ.FileFormats.AnimSet)Mooege.Common.MPQ.MPQStorage.Data.Assets[SNOGroup.AnimSet][this.ActorData.AnimSetSNO].Data; @@ -261,7 +258,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem // Listen for quest progress if the actor has a QuestRange attached to it //foreach (var quest in World.Game.QuestManager.Quests) if (_questRange != null) - World.Game.QuestManager.OnQuestProgress += new QuestManager.QuestProgressDelegate(quest_OnQuestProgress); + World.Game.QuestManager.OnQuestProgress += quest_OnQuestProgress; UpdateQuestRangeVisibility(); } diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/ActorFactory.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/ActorFactory.cs index bc0d8b9..a75002a 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/ActorFactory.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/ActorFactory.cs @@ -39,7 +39,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem { if (!MPQStorage.Data.Assets[SNOGroup.Actor].ContainsKey((int)sno)) { - //Logger.Warn("Actor asset not found, Id: {0}", snoId); + Logger.Error("$[underline on white]$Actor asset not found$[/]$, Id: $[underline white]${0}$[/]$ - $[underline white]${1}$[/]$", (int)sno, sno.ToString()); return null; } @@ -77,7 +77,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem return null; var actorAsset = MPQStorage.Data.Assets[SNOGroup.Actor][(int)sno]; - var actorData = actorAsset.Data as DiIiS_NA.Core.MPQ.FileFormats.Actor; + var actorData = actorAsset.Data as DiIiS_NA.Core.MPQ.FileFormats.ActorData; if (actorData == null) { Logger.Warn("Actor data not found, Id: {0}", sno); diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/BossPortal.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/BossPortal.cs index 0972df1..30f39d6 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/BossPortal.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/BossPortal.cs @@ -48,7 +48,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem Attributes[GameAttribute.MinimapActive] = true; Attributes[GameAttribute.Untargetable] = false; - var bossEncounter = ((ActorSNO.Target as DiIiS_NA.Core.MPQ.FileFormats.Actor).TagMap[MarkerKeys.BossEncounter].Target as DiIiS_NA.Core.MPQ.FileFormats.BossEncounter); + var bossEncounter = ((ActorSNO.Target as DiIiS_NA.Core.MPQ.FileFormats.ActorData).TagMap[MarkerKeys.BossEncounter].Target as DiIiS_NA.Core.MPQ.FileFormats.BossEncounter); DestWorld = bossEncounter.Worlds[0]; switch (DestWorld) { diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Minion.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Minion.cs index fa1d412..0ef98a6 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Minion.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Minion.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using MonsterFF = DiIiS_NA.Core.MPQ.FileFormats.Monster; -using ActorFF = DiIiS_NA.Core.MPQ.FileFormats.Actor; using DiIiS_NA.GameServer.MessageSystem.Message.Definitions.Pet; using DiIiS_NA.GameServer.GSSystem.PlayerSystem; using DiIiS_NA.GameServer.MessageSystem; diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Spawner.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Spawner.cs index a86414d..76fc96e 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Spawner.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ActorSystem/Spawner.cs @@ -96,7 +96,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ActorSystem }; //this.World.Game.WorldGenerator.Actions.Enqueue(() => - World.Game.WorldGenerator.LoadActor(ActorToSpawnSNO, location, World, ((DiIiS_NA.Core.MPQ.FileFormats.Actor)ActorToSpawnSNO.Target).TagMap); + World.Game.WorldGenerator.LoadActor(ActorToSpawnSNO, location, World, ((DiIiS_NA.Core.MPQ.FileFormats.ActorData)ActorToSpawnSNO.Target).TagMap); //Mooege.Core.GS.Generators.WorldGenerator.loadActor(ActorToSpawnSNO, location, this.World, ((Mooege.Common.MPQ.FileFormats.Actor)ActorToSpawnSNO.Target).TagMap); } diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/GeneratorsSystem/WorldGenerator.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/GeneratorsSystem/WorldGenerator.cs index abef534..695a639 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/GeneratorsSystem/WorldGenerator.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/GeneratorsSystem/WorldGenerator.cs @@ -2226,7 +2226,7 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem /// The world to which to add loaded actors private void LoadLevelAreas(Dictionary> levelAreas, World world) { - Dictionary dict = new Dictionary(); + Dictionary dict = new Dictionary(); foreach (int la in levelAreas.Keys) { SNOHandle levelAreaHandle = new SNOHandle(SNOGroup.LevelArea, la); @@ -2270,7 +2270,7 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem { var handle = new SNOHandle(207706); if (handle == null || gizmoLocations.Count == 0) continue; - LazyLoadActor(handle, gizmoLocations.PickRandom(), world, ((DiIiS_NA.Core.MPQ.FileFormats.Actor)handle.Target).TagMap); + LazyLoadActor(handle, gizmoLocations.PickRandom(), world, ((DiIiS_NA.Core.MPQ.FileFormats.ActorData)handle.Target).TagMap); } else foreach (var location in gizmoLocations) @@ -2290,7 +2290,7 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem seed -= pair.Value; } if (gizmoHandle == null) continue; - LazyLoadActor(gizmoHandle, location, world, ((DiIiS_NA.Core.MPQ.FileFormats.Actor)gizmoHandle.Target).TagMap); + LazyLoadActor(gizmoHandle, location, world, ((DiIiS_NA.Core.MPQ.FileFormats.ActorData)gizmoHandle.Target).TagMap); } } @@ -2298,7 +2298,7 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem { var handleChest = new SNOHandle(96993); //leg chest if (handleChest == null) continue; - var goldenChest = LoadActor(handleChest, gizmoLocations.PickRandom(), world, ((DiIiS_NA.Core.MPQ.FileFormats.Actor)handleChest.Target).TagMap); + var goldenChest = LoadActor(handleChest, gizmoLocations.PickRandom(), world, ((DiIiS_NA.Core.MPQ.FileFormats.ActorData)handleChest.Target).TagMap); if (goldenChest > 0) (world.GetActorByGlobalId(goldenChest) as LegendaryChest).ChestActive = true; } @@ -2657,43 +2657,55 @@ namespace DiIiS_NA.GameServer.GSSystem.GeneratorsSystem //TODO: Move this out as loading actors can happen even after world was generated public uint LoadActor(SNOHandle actorHandle, PRTransform location, World world, TagMap tagMap, MonsterType monsterType = MonsterType.Default, int groupId = 0) { - var actorSno = (ActorSno)actorHandle.Id; // TODO: maybe we can replace SNOHandle - if (world.QuadTree.Query(new Core.Types.Misc.Circle(location.Vector3D.X, location.Vector3D.Y, 60f)).Count > 0 || - world.QuadTree.Query(new Core.Types.Misc.Circle(location.Vector3D.X, location.Vector3D.Y, 5f)).Count > 0) + try { - Logger.Debug("Load actor {0} ignored - waypoint nearby.", actorSno); + var actorSno = (ActorSno)actorHandle.Id; // TODO: maybe we can replace SNOHandle + if (world.QuadTree + .Query(new Core.Types.Misc.Circle(location.Vector3D.X, location.Vector3D.Y, 60f)) + .Count > 0 || + world.QuadTree + .Query(new Core.Types.Misc.Circle(location.Vector3D.X, location.Vector3D.Y, 5f)).Count > + 0) + { + Logger.Debug("Load actor {0} ignored - waypoint nearby.", actorSno); + return 0; + } + + var actor = ActorFactory.Create(world, actorSno, tagMap); + + switch (monsterType) + { + case MonsterType.Champion: + actor = new Champion(world, actorSno, tagMap); + actor.GroupId = groupId; + break; + case MonsterType.Elite: + actor = new Rare(world, actorSno, tagMap); + actor.GroupId = groupId; + break; + case MonsterType.EliteMinion: + actor = new RareMinion(world, actorSno, tagMap); + actor.GroupId = groupId; + break; + } + + if (actor == null) + { + if (actorSno != ActorSno.__NONE) + Logger.Warn("ActorFactory did not load actor {0}", actorHandle); + return 0; + } + + actor.RotationW = location.Quaternion.W; + actor.RotationAxis = location.Quaternion.Vector3D; + actor.EnterWorld(location.Vector3D); + return actor.GlobalID; + } + catch (Exception ex) + { + Logger.Error("Error loading actor {0} at {1}", actorHandle.Id, location); return 0; } - - var actor = ActorFactory.Create(world, actorSno, tagMap); - - switch (monsterType) - { - case MonsterType.Champion: - actor = new Champion(world, actorSno, tagMap); - actor.GroupId = groupId; - break; - case MonsterType.Elite: - actor = new Rare(world, actorSno, tagMap); - actor.GroupId = groupId; - break; - case MonsterType.EliteMinion: - actor = new RareMinion(world, actorSno, tagMap); - actor.GroupId = groupId; - break; - } - - if (actor == null) - { - if (actorSno != ActorSno.__NONE) - Logger.Warn("ActorFactory did not load actor {0}", actorHandle); - return 0; - } - - actor.RotationW = location.Quaternion.W; - actor.RotationAxis = location.Quaternion.Vector3D; - actor.EnterWorld(location.Vector3D); - return actor.GlobalID; } public void LazyLoadActor(SNOHandle actorHandle, PRTransform location, World world, TagMap tagMap, MonsterType monsterType = MonsterType.Default) diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/ItemsSystem/Implementations/Book.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ItemsSystem/Implementations/Book.cs index 9ecf952..4a59ac5 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/ItemsSystem/Implementations/Book.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ItemsSystem/Implementations/Book.cs @@ -14,7 +14,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ItemsSystem.Implementations public Book(MapSystem.World world, DiIiS_NA.Core.MPQ.FileFormats.GameBalance.ItemTable definition, int cork = -1, bool cork2 = false, int cork3 = -1) : base(world, definition) { - var actorData = ActorSNO.Target as DiIiS_NA.Core.MPQ.FileFormats.Actor; + var actorData = ActorSNO.Target as DiIiS_NA.Core.MPQ.FileFormats.ActorData; if (actorData.TagMap.ContainsKey(ActorKeys.Lore)) { diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/ItemsSystem/ItemGenerator.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ItemsSystem/ItemGenerator.cs index 09e3b29..3d06539 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/ItemsSystem/ItemGenerator.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ItemsSystem/ItemGenerator.cs @@ -443,7 +443,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ItemsSystem { foreach (var asset in MPQStorage.Data.Assets[SNOGroup.Actor].Values) { - Actor data = asset.Data as Actor; + ActorData data = asset.Data as ActorData; if (data != null && data.TagMap.ContainsKey(ActorKeys.Lore)) { if (Lore.ContainsKey(data.TagMap[ActorKeys.Lore].Id)) continue; diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/ObjectsSystem/DynamicObject.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/ObjectsSystem/DynamicObject.cs index 7736a81..c30feeb 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/ObjectsSystem/DynamicObject.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/ObjectsSystem/DynamicObject.cs @@ -14,13 +14,7 @@ namespace DiIiS_NA.GameServer.GSSystem.ObjectsSystem /// public uint GlobalID { - get - { - if (GlobalIDOverride > 0) - return GlobalIDOverride; - else - return _globalID; - } + get => GlobalIDOverride > 0 ? GlobalIDOverride : _globalID; private set { } } diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/PlayerSystem/Player.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/PlayerSystem/Player.cs index 82b6c86..9b80b47 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/PlayerSystem/Player.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/PlayerSystem/Player.cs @@ -1680,7 +1680,7 @@ public class Player : Actor, IMessageConsumer, IUpdateable public void OnHirelingSwapAgreeMessage() { Hireling hireling = null; - DiIiS_NA.Core.MPQ.FileFormats.Actor Data = null; + DiIiS_NA.Core.MPQ.FileFormats.ActorData Data = null; if (World.Game.Players.Count > 1) return; @@ -1688,20 +1688,20 @@ public class Player : Actor, IMessageConsumer, IUpdateable { case 72061: //Templar - Data = (DiIiS_NA.Core.MPQ.FileFormats.Actor)MPQStorage.Data.Assets[SNOGroup.Actor][52693].Data; + Data = (DiIiS_NA.Core.MPQ.FileFormats.ActorData)MPQStorage.Data.Assets[SNOGroup.Actor][52693].Data; hireling = new Templar(World, ActorSno._hireling_templar, Data.TagMap); hireling.GBHandle.GBID = StringHashHelper.HashItemName("Templar"); break; case 72738: //Scoundrel - Data = (DiIiS_NA.Core.MPQ.FileFormats.Actor)MPQStorage.Data.Assets[SNOGroup.Actor][52694].Data; + Data = (DiIiS_NA.Core.MPQ.FileFormats.ActorData)MPQStorage.Data.Assets[SNOGroup.Actor][52694].Data; hireling = new Templar(World, ActorSno._hireling_scoundrel, Data.TagMap); hireling.GBHandle.GBID = StringHashHelper.HashItemName("Scoundrel"); break; case 0: //Enchantress - Data = (DiIiS_NA.Core.MPQ.FileFormats.Actor)MPQStorage.Data.Assets[SNOGroup.Actor][4482].Data; + Data = (DiIiS_NA.Core.MPQ.FileFormats.ActorData)MPQStorage.Data.Assets[SNOGroup.Actor][4482].Data; hireling = new Templar(World, ActorSno._hireling_enchantress, Data.TagMap); hireling.GBHandle.GBID = StringHashHelper.HashItemName("Enchantress"); break; diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/ActI.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/ActI.cs index e2e57bc..c80aa38 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/ActI.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/ActI.cs @@ -1426,13 +1426,14 @@ namespace DiIiS_NA.GameServer.GSSystem.QuestSystem Completed = false, Saveable = true, NextStep = 14, - Objectives = new List { Objective.Default(), Objective.Default() }, + Objectives = new List { Objective.WithLimit(2) }, OnAdvance = () => { //find 2 Orbs DestroyFollower(ActorSno._leah); - AddFollower(Game.GetWorld(WorldSno.trout_town), ActorSno._leah); + var world = Game.GetWorld(WorldSno.trout_town); + AddFollower(world, ActorSno._leah); ListenInteract(ActorSno._a1dun_caves_nephalem_altar_a_chest_03, 1, new CompleteObjective(0)); - ListenInteract(ActorSno._a1dun_caves_nephalem_altar_a_chest_03_b, 1, new CompleteObjective(1)); + ListenInteract(ActorSno._a1dun_caves_nephalem_altar_a_chest_03_b, 1, new CompleteObjective(0)); } }); @@ -1441,7 +1442,7 @@ namespace DiIiS_NA.GameServer.GSSystem.QuestSystem Completed = false, Saveable = true, NextStep = 30, - Objectives = new List { new Objective { Limit = 2, Counter = 0 } }, + Objectives = new List { Objective.WithLimit(2) }, OnAdvance = () => { //use 2 stones var world = Game.GetWorld(WorldSno.trout_town); diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestEvents/Implementations/Act I/SpawnMiraImon.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestEvents/Implementations/Act I/SpawnMiraImon.cs index abed6b7..b50a32d 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestEvents/Implementations/Act I/SpawnMiraImon.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestEvents/Implementations/Act I/SpawnMiraImon.cs @@ -68,7 +68,7 @@ namespace DiIiS_NA.GameServer.GSSystem.QuestSystem.QuestEvents.Implementations { var counter = 0; var monsterSNOHandle = new Core.Types.SNO.SNOHandle(SnoId); - var monsterActor = monsterSNOHandle.Target as DiIiS_NA.Core.MPQ.FileFormats.Actor; + var monsterActor = monsterSNOHandle.Target as DiIiS_NA.Core.MPQ.FileFormats.ActorData; foreach (Vector3D coords in Coordinates) { diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestEvents/Implementations/Act II/SpawnSnakemans.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestEvents/Implementations/Act II/SpawnSnakemans.cs index 72a9860..e23bf55 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestEvents/Implementations/Act II/SpawnSnakemans.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestEvents/Implementations/Act II/SpawnSnakemans.cs @@ -18,7 +18,7 @@ namespace DiIiS_NA.GameServer.GSSystem.QuestSystem.QuestEvents.Implementations //Logger.Trace("SpawnSnakemans event started"); var point = new Vector3D { X = 835.331f, Y = 410.121f, Z = 161.842f }; var snakeManHandle = new Core.Types.SNO.SNOHandle((int)ActorSno._khamsin_snakeman_melee); - var snakeManActor = snakeManHandle.Target as DiIiS_NA.Core.MPQ.FileFormats.Actor; + var snakeManActor = snakeManHandle.Target as DiIiS_NA.Core.MPQ.FileFormats.ActorData; try { var caldeumGuard = world.FindActorAt(ActorSno._caldeumguard_cleaver_a, point, 20.0f); diff --git a/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestProgress.cs b/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestProgress.cs index 3aeb5da..f624206 100644 --- a/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestProgress.cs +++ b/src/DiIiS-NA/D3-GameServer/GSSystem/QuestSystem/QuestProgress.cs @@ -55,6 +55,7 @@ namespace DiIiS_NA.GameServer.GSSystem.QuestSystem public int Counter; public static Objective Default() => new () { Limit = 1, Counter = 0 }; + public static Objective WithLimit(int limit) => new () { Limit = limit, Counter = 0 }; } // key can be ActorSno (also multiplied), DestLevelAreaSno, ConversationSno