diff --git a/Intersect.Client/Core/Audio.cs b/Intersect.Client/Core/Audio.cs index 37c51780c6..172f780367 100644 --- a/Intersect.Client/Core/Audio.cs +++ b/Intersect.Client/Core/Audio.cs @@ -7,298 +7,296 @@ using Intersect.Logging; using Intersect.Utilities; -namespace Intersect.Client.Core -{ +namespace Intersect.Client.Core; - public static partial class Audio - { - private static string sCurrentSong = ""; +public static partial class Audio +{ - private static int sFadeRate; + private static string sCurrentSong = ""; - private static long sFadeTimer; + private static int sFadeRate; - private static bool sFadingOut; + private static long sFadeTimer; - //Sounds - private static List sGameSounds = new List(); + private static bool sFadingOut; - private static bool sIsInitialized; + //Sounds + private static List sGameSounds = new List(); - private static int sQueuedFade; + private static bool sIsInitialized; - private static bool sQueuedLoop; + private static int sQueuedFade; - //Music - private static string sQueuedMusic = ""; + private static bool sQueuedLoop; - private static GameAudioInstance sMyMusic { get; set; } + //Music + private static string sQueuedMusic = ""; - //Init - public static void Init() - { - if (sIsInitialized == true) - { - return; - } + private static GameAudioInstance sMyMusic { get; set; } - Globals.ContentManager.LoadAudio(); - sIsInitialized = true; + //Init + public static void Init() + { + if (sIsInitialized == true) + { + return; } - public static void UpdateGlobalVolume() + Globals.ContentManager.LoadAudio(); + sIsInitialized = true; + } + + public static void UpdateGlobalVolume() + { + if (sMyMusic != null) { - if (sMyMusic != null) - { - sMyMusic.SetVolume(sMyMusic.GetVolume(), true); - } + sMyMusic.SetVolume(sMyMusic.GetVolume(), true); + } - for (var i = 0; i < sGameSounds.Count; i++) + for (var i = 0; i < sGameSounds.Count; i++) + { + sGameSounds[i].Update(); + if (!sGameSounds[i].Loaded) { - sGameSounds[i].Update(); - if (!sGameSounds[i].Loaded) - { - sGameSounds.RemoveAt(i); - } + sGameSounds.RemoveAt(i); } } + } - //Update - public static void Update() + //Update + public static void Update() + { + if (sMyMusic != null) { - if (sMyMusic != null) + var currentTime = Timing.Global.MillisecondsUtc; + if (sFadeTimer != 0 && sFadeTimer < currentTime) { - var currentTime = Timing.Global.MillisecondsUtc; - if (sFadeTimer != 0 && sFadeTimer < currentTime) + if (sFadingOut) { - if (sFadingOut) + sMyMusic.SetVolume(sMyMusic.GetVolume() - 1, true); + if (sMyMusic.GetVolume() <= 1) { - sMyMusic.SetVolume(sMyMusic.GetVolume() - 1, true); - if (sMyMusic.GetVolume() <= 1) - { - StopMusic(); - PlayMusic(sQueuedMusic, 0, sQueuedFade, sQueuedLoop); - } - else - { - sFadeTimer = currentTime + sFadeRate; - } + StopMusic(); + PlayMusic(sQueuedMusic, 0, sQueuedFade, sQueuedLoop); } else { - sMyMusic.SetVolume(sMyMusic.GetVolume() + 1, true); - if (sMyMusic.GetVolume() < 100) - { - sFadeTimer = currentTime + sFadeRate; - } - else - { - sFadeTimer = 0; - } + sFadeTimer = currentTime + sFadeRate; } } - } - - for (var i = 0; i < sGameSounds.Count; i++) - { - sGameSounds[i].Update(); - if (!sGameSounds[i].Loaded) - { - sGameSounds.RemoveAt(i); - } - } - - // Update our pack sound cache if we have any packs loaded. - if (Globals.ContentManager.SoundPacks != null) - { - Globals.ContentManager.SoundPacks.UpdateCache(); - } - - // Update our pack music cache if we have any packs loaded. - if (Globals.ContentManager.MusicPacks != null) - { - Globals.ContentManager.MusicPacks.UpdateCache(); - } - } - - //Music - /// - /// Play a music track, automatically fading out the old track with the configured values. - /// - /// The song file name to start playing. A blank filename will only stop the currently playing music track. - /// The time (in ms) it should take to fade in the new music track. - /// The time (in ms) it should take to fade out the current music track. - /// Determines whether the song loops once it's over or not. - public static void PlayMusic(string filename, int fadeout = 0, int fadein = 0, bool loop = false) - { - if (string.IsNullOrWhiteSpace(filename)) - { - //Entered a map with no music selected, fade out any music that's already playing. - StopMusic(fadeout); - - return; - } - - ClearQueue(); - - filename = GameContentManager.RemoveExtension(filename); - if (sMyMusic != null) - { - if (fadeout == 0 || - sMyMusic.State == GameAudioInstance.AudioInstanceState.Stopped || - sMyMusic.State == GameAudioInstance.AudioInstanceState.Paused || - sMyMusic.GetVolume() == 0) - { - StopMusic(); - StartMusic(filename, fadein, loop); - } else { - //Start fadeout - if (!string.Equals(sCurrentSong, filename, StringComparison.CurrentCultureIgnoreCase) || sFadingOut) + sMyMusic.SetVolume(sMyMusic.GetVolume() + 1, true); + if (sMyMusic.GetVolume() < 100) { - StopMusic(fadeout); - sQueuedMusic = filename; - sQueuedFade = fadein; - sQueuedLoop = loop; + sFadeTimer = currentTime + sFadeRate; + } + else + { + sFadeTimer = 0; } } } - else + } + + for (var i = 0; i < sGameSounds.Count; i++) + { + sGameSounds[i].Update(); + if (!sGameSounds[i].Loaded) { - StartMusic(filename, fadein, loop); + sGameSounds.RemoveAt(i); } } - private static void ClearQueue() + // Update our pack sound cache if we have any packs loaded. + if (Globals.ContentManager.SoundPacks != null) { - sQueuedMusic = null; - sQueuedLoop = false; - sQueuedFade = -1; + Globals.ContentManager.SoundPacks.UpdateCache(); } - /// - /// Start playing a new music track. - /// - /// The song file name to start playing. - /// The time (in ms) it should take to fade in the new music track. - /// Determines whether the song loops once it's over or not. - private static void StartMusic(string filename, int fadein = 0, bool loop = false) + // Update our pack music cache if we have any packs loaded. + if (Globals.ContentManager.MusicPacks != null) { - var music = Globals.ContentManager.GetMusic(filename); - if (music == null) - { - return; - } + Globals.ContentManager.MusicPacks.UpdateCache(); + } + } - if (sMyMusic != null) - { - Log.Warn($"Trying to start '{filename}' without properly closing '{sCurrentSong}'."); - } + //Music + /// + /// Play a music track, automatically fading out the old track with the configured values. + /// + /// The song file name to start playing. A blank filename will only stop the currently playing music track. + /// The time (in ms) it should take to fade in the new music track. + /// The time (in ms) it should take to fade out the current music track. + /// Determines whether the song loops once it's over or not. + public static void PlayMusic(string filename, int fadeout = 0, int fadein = 0, bool loop = false) + { + if (string.IsNullOrWhiteSpace(filename)) + { + //Entered a map with no music selected, fade out any music that's already playing. + StopMusic(fadeout); - sMyMusic = music.CreateInstance(); - sCurrentSong = filename; - sMyMusic.Play(); - sMyMusic.SetVolume(0, true); - sMyMusic.IsLooping = loop; - sFadeRate = fadein / 100; - sFadeTimer = Timing.Global.MillisecondsUtc + sFadeRate; - sFadingOut = false; + return; } - /// - /// Stops the current playing music track. - /// - /// The time (in ms) it should take to fade out the current music track. - public static void StopMusic(int fadeout = 0) - { - if (sMyMusic == null) - { - return; - } + ClearQueue(); + filename = GameContentManager.RemoveExtension(filename); + if (sMyMusic != null) + { if (fadeout == 0 || sMyMusic.State == GameAudioInstance.AudioInstanceState.Stopped || sMyMusic.State == GameAudioInstance.AudioInstanceState.Paused || sMyMusic.GetVolume() == 0) { - sCurrentSong = ""; - sMyMusic.Stop(); - sMyMusic.Dispose(); - sMyMusic = null; - sFadeTimer = 0; + StopMusic(); + StartMusic(filename, fadein, loop); } else { //Start fadeout - sFadeRate = fadeout / sMyMusic.GetVolume(); - sFadeTimer = Timing.Global.MillisecondsUtc + sFadeRate; - sFadingOut = true; + if (!string.Equals(sCurrentSong, filename, StringComparison.CurrentCultureIgnoreCase) || sFadingOut) + { + StopMusic(fadeout); + sQueuedMusic = filename; + sQueuedFade = fadein; + sQueuedLoop = loop; + } } } - - //Sounds - public static MapSound AddMapSound( - string filename, - int x, - int y, - Guid mapId, - bool loop, - int loopInterval, - int distance, - IEntity parent = null - ) + else { - if (sGameSounds?.Count > 128) - { - return null; - } + StartMusic(filename, fadein, loop); + } + } - var sound = new MapSound(filename, x, y, mapId, loop, loopInterval, distance, parent); - sGameSounds?.Add(sound); + private static void ClearQueue() + { + sQueuedMusic = null; + sQueuedLoop = false; + sQueuedFade = -1; + } - return sound; + /// + /// Start playing a new music track. + /// + /// The song file name to start playing. + /// The time (in ms) it should take to fade in the new music track. + /// Determines whether the song loops once it's over or not. + private static void StartMusic(string filename, int fadein = 0, bool loop = false) + { + var music = Globals.ContentManager.GetMusic(filename); + if (music == null) + { + return; } - public static Sound AddGameSound(string filename, bool loop) + if (sMyMusic != null) { - if (sGameSounds?.Count > 128) - { - return null; - } + Log.Warn($"Trying to start '{filename}' without properly closing '{sCurrentSong}'."); + } - var sound = new Sound(filename, loop, 0); - sGameSounds?.Add(sound); + sMyMusic = music.CreateInstance(); + sCurrentSong = filename; + sMyMusic.Play(); + sMyMusic.SetVolume(0, true); + sMyMusic.IsLooping = loop; + sFadeRate = fadein / 100; + sFadeTimer = Timing.Global.MillisecondsUtc + sFadeRate; + sFadingOut = false; + } - return sound; + /// + /// Stops the current playing music track. + /// + /// The time (in ms) it should take to fade out the current music track. + public static void StopMusic(int fadeout = 0) + { + if (sMyMusic == null) + { + return; } - public static void StopSound(IMapSound sound) + if (fadeout == 0 || + sMyMusic.State == GameAudioInstance.AudioInstanceState.Stopped || + sMyMusic.State == GameAudioInstance.AudioInstanceState.Paused || + sMyMusic.GetVolume() == 0) { - sound?.Stop(); + sCurrentSong = ""; + sMyMusic.Stop(); + sMyMusic.Dispose(); + sMyMusic = null; + sFadeTimer = 0; } + else + { + //Start fadeout + sFadeRate = fadeout / sMyMusic.GetVolume(); + sFadeTimer = Timing.Global.MillisecondsUtc + sFadeRate; + sFadingOut = true; + } + } - public static void StopAllGameSoundsOf(string[] filenames) + //Sounds + public static MapSound AddMapSound( + string filename, + int x, + int y, + Guid mapId, + bool loop, + int loopInterval, + int distance, + IEntity parent = null + ) + { + if (sGameSounds?.Count > 128) { - var validSounds = sGameSounds.Where(s => filenames.Contains(s.Filename)); - foreach (var sound in validSounds) - { - sound.Stop(); - } + return null; } - public static void StopAllSounds() + var sound = new MapSound(filename, x, y, mapId, loop, loopInterval, distance, parent); + sGameSounds?.Add(sound); + + return sound; + } + + public static Sound AddGameSound(string filename, bool loop) + { + if (sGameSounds?.Count > 128) { - for (var i = 0; i < sGameSounds.Count; i++) + return null; + } + + var sound = new Sound(filename, loop, 0); + sGameSounds?.Add(sound); + + return sound; + } + + public static void StopSound(IMapSound sound) + { + sound?.Stop(); + } + + public static void StopAllGameSoundsOf(string[] filenames) + { + var validSounds = sGameSounds.Where(s => filenames.Contains(s.Filename)); + foreach (var sound in validSounds) + { + sound.Stop(); + } + } + + public static void StopAllSounds() + { + for (var i = 0; i < sGameSounds.Count; i++) + { + if (sGameSounds[i] != null) { - if (sGameSounds[i] != null) - { - sGameSounds[i].Stop(); - } + sGameSounds[i].Stop(); } } - } } diff --git a/Intersect.Client/Core/Bootstrapper.cs b/Intersect.Client/Core/Bootstrapper.cs index bbbfe7d820..9379358710 100644 --- a/Intersect.Client/Core/Bootstrapper.cs +++ b/Intersect.Client/Core/Bootstrapper.cs @@ -7,93 +7,91 @@ using Intersect.Plugins.Contexts; using Intersect.Plugins.Helpers; -namespace Intersect.Client.Core +namespace Intersect.Client.Core; + + +internal static partial class Bootstrapper { + public static ClientContext Context { get; private set; } - internal static partial class Bootstrapper + public static void Start(params string[] args) { - public static ClientContext Context { get; private set; } - - public static void Start(params string[] args) - { - var parser = new Parser( - parserSettings => + var parser = new Parser( + parserSettings => + { + if (parserSettings == null) { - if (parserSettings == null) - { - throw new ArgumentNullException( - nameof(parserSettings), @"If this is null the CommandLineParser dependency is likely broken." - ); - } - - parserSettings.AutoHelp = true; - parserSettings.AutoVersion = true; - parserSettings.IgnoreUnknownArguments = true; + throw new ArgumentNullException( + nameof(parserSettings), @"If this is null the CommandLineParser dependency is likely broken." + ); } - ); - var logger = Log.Default; - var packetTypeRegistry = new PacketTypeRegistry(logger); - if (!packetTypeRegistry.TryRegisterBuiltIn()) - { - logger.Error("Failed to register built-in packets."); - return; + parserSettings.AutoHelp = true; + parserSettings.AutoVersion = true; + parserSettings.IgnoreUnknownArguments = true; } + ); - var packetHandlerRegistry = new PacketHandlerRegistry(packetTypeRegistry, logger); - var packetHelper = new PacketHelper(packetTypeRegistry, packetHandlerRegistry); - FactoryRegistry.RegisterFactory(PluginBootstrapContext.CreateFactory(args, parser, packetHelper)); + var logger = Log.Default; + var packetTypeRegistry = new PacketTypeRegistry(logger); + if (!packetTypeRegistry.TryRegisterBuiltIn()) + { + logger.Error("Failed to register built-in packets."); + return; + } - var commandLineOptions = parser.ParseArguments(args) - .MapResult(HandleParsedArguments, HandleParserErrors); + var packetHandlerRegistry = new PacketHandlerRegistry(packetTypeRegistry, logger); + var packetHelper = new PacketHelper(packetTypeRegistry, packetHandlerRegistry); + FactoryRegistry.RegisterFactory(PluginBootstrapContext.CreateFactory(args, parser, packetHelper)); - if (!string.IsNullOrWhiteSpace(commandLineOptions.WorkingDirectory)) + var commandLineOptions = parser.ParseArguments(args) + .MapResult(HandleParsedArguments, HandleParserErrors); + + if (!string.IsNullOrWhiteSpace(commandLineOptions.WorkingDirectory)) + { + var workingDirectory = commandLineOptions.WorkingDirectory.Trim(); + var resolvedWorkingDirectory = Path.GetFullPath(workingDirectory); + if (Directory.Exists(resolvedWorkingDirectory)) { - var workingDirectory = commandLineOptions.WorkingDirectory.Trim(); - var resolvedWorkingDirectory = Path.GetFullPath(workingDirectory); - if (Directory.Exists(resolvedWorkingDirectory)) - { - Environment.CurrentDirectory = resolvedWorkingDirectory; - } - else - { - Log.Warn($"Failed to set working directory to '{workingDirectory}', path does not exist: {resolvedWorkingDirectory}"); - } + Environment.CurrentDirectory = resolvedWorkingDirectory; + } + else + { + Log.Warn($"Failed to set working directory to '{workingDirectory}', path does not exist: {resolvedWorkingDirectory}"); } - - Context = new ClientContext(commandLineOptions, logger, packetHelper); - Context.Start(); } - private static ClientCommandLineOptions HandleParsedArguments(ClientCommandLineOptions clientCommandLineOptions) => - clientCommandLineOptions; + Context = new ClientContext(commandLineOptions, logger, packetHelper); + Context.Start(); + } - private static ClientCommandLineOptions HandleParserErrors(IEnumerable errors) - { - var errorsAsList = errors?.ToList(); + private static ClientCommandLineOptions HandleParsedArguments(ClientCommandLineOptions clientCommandLineOptions) => + clientCommandLineOptions; - var fatalParsingError = errorsAsList?.Any(error => error?.StopsProcessing ?? false) ?? false; + private static ClientCommandLineOptions HandleParserErrors(IEnumerable errors) + { + var errorsAsList = errors?.ToList(); - var errorString = string.Join( - ", ", errorsAsList?.ToList().Select(error => error?.ToString()) ?? Array.Empty() - ); + var fatalParsingError = errorsAsList?.Any(error => error?.StopsProcessing ?? false) ?? false; - var exception = new ArgumentException( - $@"Error parsing command line arguments, received the following errors: {errorString}" - ); + var errorString = string.Join( + ", ", errorsAsList?.ToList().Select(error => error?.ToString()) ?? Array.Empty() + ); - if (fatalParsingError) - { - Log.Error(exception); - } - else - { - Log.Warn(exception); - } + var exception = new ArgumentException( + $@"Error parsing command line arguments, received the following errors: {errorString}" + ); - return default; + if (fatalParsingError) + { + Log.Error(exception); + } + else + { + Log.Warn(exception); } + return default; } } diff --git a/Intersect.Client/Core/ClientCommandLineOptions.cs b/Intersect.Client/Core/ClientCommandLineOptions.cs index 3c72776e0f..cf99e425cc 100644 --- a/Intersect.Client/Core/ClientCommandLineOptions.cs +++ b/Intersect.Client/Core/ClientCommandLineOptions.cs @@ -3,46 +3,45 @@ using Intersect.Client.Framework.Graphics; using Intersect.Core; -namespace Intersect.Client.Core +namespace Intersect.Client.Core; + +internal partial struct ClientCommandLineOptions : ICommandLineOptions { - internal partial struct ClientCommandLineOptions : ICommandLineOptions + public ClientCommandLineOptions( + bool borderlessWindow, + int screenWidth, + int screenHeight, + string server, + string workingDirectory, + IEnumerable pluginDirectories + ) { - public ClientCommandLineOptions( - bool borderlessWindow, - int screenWidth, - int screenHeight, - string server, - string workingDirectory, - IEnumerable pluginDirectories - ) - { - BorderlessWindow = borderlessWindow; - ScreenWidth = screenWidth; - ScreenHeight = screenHeight; - Server = server; - WorkingDirectory = workingDirectory; - PluginDirectories = pluginDirectories?.Select(Path.GetFullPath).ToArray(); - } - - [Option("borderless", Default = false, Required = false)] - public bool BorderlessWindow { get; } - - [Option("screen-width", Default = 0, Required = false)] - public int ScreenWidth { get; } - - [Option("screen-height", Default = 0, Required = false)] - public int ScreenHeight { get; } - - [Option('S', "server", Default = null, Required = false)] - public string Server { get; } - - [Option("working-directory", Default = null, Required = false)] - public string WorkingDirectory { get; } - - [Option('p', "plugin-directory", Default = null, Required = false)] - public IEnumerable PluginDirectories { get; } - - public Resolution ScreenResolution => new Resolution(ScreenWidth, ScreenHeight); - + BorderlessWindow = borderlessWindow; + ScreenWidth = screenWidth; + ScreenHeight = screenHeight; + Server = server; + WorkingDirectory = workingDirectory; + PluginDirectories = pluginDirectories?.Select(Path.GetFullPath).ToArray(); } + + [Option("borderless", Default = false, Required = false)] + public bool BorderlessWindow { get; } + + [Option("screen-width", Default = 0, Required = false)] + public int ScreenWidth { get; } + + [Option("screen-height", Default = 0, Required = false)] + public int ScreenHeight { get; } + + [Option('S', "server", Default = null, Required = false)] + public string Server { get; } + + [Option("working-directory", Default = null, Required = false)] + public string WorkingDirectory { get; } + + [Option('p', "plugin-directory", Default = null, Required = false)] + public IEnumerable PluginDirectories { get; } + + public Resolution ScreenResolution => new Resolution(ScreenWidth, ScreenHeight); + } diff --git a/Intersect.Client/Core/ClientContext.cs b/Intersect.Client/Core/ClientContext.cs index e2fd923b58..adcb194e77 100644 --- a/Intersect.Client/Core/ClientContext.cs +++ b/Intersect.Client/Core/ClientContext.cs @@ -7,69 +7,68 @@ using Intersect.Plugins.Interfaces; using Intersect.Reflection; -namespace Intersect.Client.Core +namespace Intersect.Client.Core; + +/// +/// Implements . +/// +internal sealed partial class ClientContext : ApplicationContext, IClientContext { - /// - /// Implements . - /// - internal sealed partial class ClientContext : ApplicationContext, IClientContext - { - internal static bool IsSinglePlayer { get; set; } + internal static bool IsSinglePlayer { get; set; } - private IPlatformRunner mPlatformRunner; + private IPlatformRunner mPlatformRunner; - internal ClientContext(ClientCommandLineOptions startupOptions, Logger logger, IPacketHelper packetHelper) : base( - startupOptions, logger, packetHelper - ) - { - FactoryRegistry.RegisterFactory(new ClientPluginContext.Factory()); - } + internal ClientContext(ClientCommandLineOptions startupOptions, Logger logger, IPacketHelper packetHelper) : base( + startupOptions, logger, packetHelper + ) + { + FactoryRegistry.RegisterFactory(new ClientPluginContext.Factory()); + } - protected override bool UsesMainThread => true; + protected override bool UsesMainThread => true; - public IPlatformRunner PlatformRunner - { - get => mPlatformRunner ?? throw new ArgumentNullException(nameof(PlatformRunner)); - private set => mPlatformRunner = value; - } + public IPlatformRunner PlatformRunner + { + get => mPlatformRunner ?? throw new ArgumentNullException(nameof(PlatformRunner)); + private set => mPlatformRunner = value; + } - /// - protected override void InternalStart() - { - Networking.Network.PacketHandler = new PacketHandler(this, PacketHelper.HandlerRegistry); - PlatformRunner = typeof(ClientContext).Assembly.CreateInstanceOf(); - PlatformRunner.Start(this, PostStartup); - } + /// + protected override void InternalStart() + { + Networking.Network.PacketHandler = new PacketHandler(this, PacketHelper.HandlerRegistry); + PlatformRunner = typeof(ClientContext).Assembly.CreateInstanceOf(); + PlatformRunner.Start(this, PostStartup); + } - #region Exception Handling + #region Exception Handling - internal static void DispatchUnhandledException( - Exception exception, - bool isTerminating = true, - bool wait = false - ) - { - var sender = Thread.CurrentThread; - var task = Task.Factory.StartNew( - () => HandleUnhandledException(sender, new UnhandledExceptionEventArgs(exception, isTerminating)) - ); + internal static void DispatchUnhandledException( + Exception exception, + bool isTerminating = true, + bool wait = false + ) + { + var sender = Thread.CurrentThread; + var task = Task.Factory.StartNew( + () => HandleUnhandledException(sender, new UnhandledExceptionEventArgs(exception, isTerminating)) + ); - if (wait) - { - task.Wait(); - } + if (wait) + { + task.Wait(); } + } - #endregion Exception Handling + #endregion Exception Handling - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); - if (disposing) - { - PacketHelper.HandlerRegistry.Dispose(); - } + if (disposing) + { + PacketHelper.HandlerRegistry.Dispose(); } } } diff --git a/Intersect.Client/Core/Controls/ControlEnum.cs b/Intersect.Client/Core/Controls/ControlEnum.cs index 70986133fe..26b5132db8 100644 --- a/Intersect.Client/Core/Controls/ControlEnum.cs +++ b/Intersect.Client/Core/Controls/ControlEnum.cs @@ -1,93 +1,91 @@ -namespace Intersect.Client.Core.Controls -{ +namespace Intersect.Client.Core.Controls; - public enum Control - { - MoveUp, +public enum Control +{ - MoveLeft, + MoveUp, - MoveDown, + MoveLeft, - MoveRight, + MoveDown, - AttackInteract, + MoveRight, - Block, + AttackInteract, - AutoTarget, + Block, - PickUp, + AutoTarget, - Enter, + PickUp, - Hotkey1, + Enter, - Hotkey2, + Hotkey1, - Hotkey3, + Hotkey2, - Hotkey4, + Hotkey3, - Hotkey5, + Hotkey4, - Hotkey6, + Hotkey5, - Hotkey7, + Hotkey6, - Hotkey8, + Hotkey7, - Hotkey9, + Hotkey8, - Hotkey0, + Hotkey9, - Screenshot, + Hotkey0, - OpenMenu, + Screenshot, - OpenInventory, + OpenMenu, - OpenQuests, + OpenInventory, - OpenCharacterInfo, + OpenQuests, - OpenParties, + OpenCharacterInfo, - OpenSpells, + OpenParties, - OpenGuild, + OpenSpells, - OpenFriends, + OpenGuild, - OpenSettings, + OpenFriends, - OpenDebugger, + OpenSettings, - OpenAdminPanel, + OpenDebugger, - ToggleGui, + OpenAdminPanel, - TurnAround, + ToggleGui, - ToggleZoomIn, + TurnAround, - HoldToZoomIn, + ToggleZoomIn, - ToggleZoomOut, + HoldToZoomIn, - HoldToZoomOut, + ToggleZoomOut, - ToggleFullscreen, + HoldToZoomOut, - // Submit, - // - // Cancel, - // - // Previous, - // - // Next, + ToggleFullscreen, - } + // Submit, + // + // Cancel, + // + // Previous, + // + // Next, } diff --git a/Intersect.Client/Core/Controls/ControlMap.cs b/Intersect.Client/Core/Controls/ControlMap.cs index 19d61c6312..6b132ed634 100644 --- a/Intersect.Client/Core/Controls/ControlMap.cs +++ b/Intersect.Client/Core/Controls/ControlMap.cs @@ -1,38 +1,37 @@ using Newtonsoft.Json; -namespace Intersect.Client.Core.Controls +namespace Intersect.Client.Core.Controls; + +public partial class ControlMap { - public partial class ControlMap + public List Bindings { get; } + + [JsonConstructor] + public ControlMap(ControlValue binding, params ControlValue[] alternateBindings) { - public List Bindings { get; } + Bindings = new List(1 + (alternateBindings?.Length ?? 0)) { binding }; + Bindings.AddRange(alternateBindings ?? Array.Empty()); - [JsonConstructor] - public ControlMap(ControlValue binding, params ControlValue[] alternateBindings) + if (Bindings.Count < 2) { - Bindings = new List(1 + (alternateBindings?.Length ?? 0)) { binding }; - Bindings.AddRange(alternateBindings ?? Array.Empty()); - - if (Bindings.Count < 2) - { - Bindings.Add(ControlValue.Default); - } + Bindings.Add(ControlValue.Default); } + } - public ControlMap(ControlMap controlMap) + public ControlMap(ControlMap controlMap) + { + if (controlMap == default) { - if (controlMap == default) - { - throw new ArgumentNullException(nameof(controlMap)); - } - - if (controlMap.Bindings.Count < 1) - { - throw new ArgumentException("The control map does not have at least one binding.", nameof(controlMap)); - } + throw new ArgumentNullException(nameof(controlMap)); + } - Bindings = controlMap.Bindings.Select(binding => new ControlValue(binding)).ToList(); + if (controlMap.Bindings.Count < 1) + { + throw new ArgumentException("The control map does not have at least one binding.", nameof(controlMap)); } - public bool KeyDown() => Bindings.Any(button => button.IsDown() && (!button.IsMouseKey || !Interface.Interface.MouseHitGui())); + Bindings = controlMap.Bindings.Select(binding => new ControlValue(binding)).ToList(); } + + public bool KeyDown() => Bindings.Any(button => button.IsDown() && (!button.IsMouseKey || !Interface.Interface.MouseHitGui())); } diff --git a/Intersect.Client/Core/Controls/ControlValue.cs b/Intersect.Client/Core/Controls/ControlValue.cs index 8a1fa434fc..1f38302b61 100644 --- a/Intersect.Client/Core/Controls/ControlValue.cs +++ b/Intersect.Client/Core/Controls/ControlValue.cs @@ -3,103 +3,102 @@ using Intersect.Client.Framework.Input; using Newtonsoft.Json; -namespace Intersect.Client.Core.Controls +namespace Intersect.Client.Core.Controls; + +public partial class ControlValue { - public partial class ControlValue - { - public static ControlValue Default => new ControlValue(Keys.None, Keys.None); + public static ControlValue Default => new ControlValue(Keys.None, Keys.None); - public Keys Modifier { get; set; } + public Keys Modifier { get; set; } - public Keys Key { get; set; } + public Keys Key { get; set; } - public bool IsMouseKey => Key == Keys.LButton - || Key == Keys.RButton - || Key == Keys.MButton - || Key == Keys.XButton1 - || Key == Keys.XButton2; + public bool IsMouseKey => Key == Keys.LButton + || Key == Keys.RButton + || Key == Keys.MButton + || Key == Keys.XButton1 + || Key == Keys.XButton2; - [JsonConstructor] - public ControlValue(Keys modifier, Keys key) - { - Modifier = modifier; - Key = key; - } + [JsonConstructor] + public ControlValue(Keys modifier, Keys key) + { + Modifier = modifier; + Key = key; + } - public ControlValue(ControlValue controlValue) + public ControlValue(ControlValue controlValue) + { + Modifier = controlValue.Modifier; + Key = controlValue.Key; + } + + public bool IsDown() + { + // Assume our modifier is clicked. + var modifier = true; + + // Check to see if it actually is, if not disable it! + if (Modifier != Keys.None && !KeyDown(Modifier)) { - Modifier = controlValue.Modifier; - Key = controlValue.Key; + modifier = false; } - public bool IsDown() + // Check to see if our modifier and real key are pressed! + if (modifier) { - // Assume our modifier is clicked. - var modifier = true; - - // Check to see if it actually is, if not disable it! - if (Modifier != Keys.None && !KeyDown(Modifier)) + if (IsMouseKey) { - modifier = false; - } - - // Check to see if our modifier and real key are pressed! - if (modifier) - { - if (IsMouseKey) + switch (Key) { - switch (Key) - { - case Keys.LButton: - if (Globals.InputManager.MouseButtonDown(MouseButtons.Left)) - { - return true; - } - - break; - case Keys.RButton: - if (Globals.InputManager.MouseButtonDown(MouseButtons.Right)) - { - return true; - } - - break; - case Keys.MButton: - if (Globals.InputManager.MouseButtonDown(MouseButtons.Middle)) - { - return true; - } - - break; - case Keys.XButton1: - if (Globals.InputManager.MouseButtonDown(MouseButtons.X1)) - { - return true; - } - - break; - case Keys.XButton2: - if (Globals.InputManager.MouseButtonDown(MouseButtons.X2)) - { - return true; - } - - break; - } + case Keys.LButton: + if (Globals.InputManager.MouseButtonDown(MouseButtons.Left)) + { + return true; + } + + break; + case Keys.RButton: + if (Globals.InputManager.MouseButtonDown(MouseButtons.Right)) + { + return true; + } + + break; + case Keys.MButton: + if (Globals.InputManager.MouseButtonDown(MouseButtons.Middle)) + { + return true; + } + + break; + case Keys.XButton1: + if (Globals.InputManager.MouseButtonDown(MouseButtons.X1)) + { + return true; + } + + break; + case Keys.XButton2: + if (Globals.InputManager.MouseButtonDown(MouseButtons.X2)) + { + return true; + } + + break; } - else + } + else + { + if (KeyDown(Key)) { - if (KeyDown(Key)) - { - return true; - } + return true; } } - - // If we get this far, clearly our buttons aren't pressed. - return false; } - - private bool KeyDown(Keys key) => Globals.InputManager.KeyDown(key); + + // If we get this far, clearly our buttons aren't pressed. + return false; } + + private bool KeyDown(Keys key) => Globals.InputManager.KeyDown(key); } diff --git a/Intersect.Client/Core/Controls/Controls.cs b/Intersect.Client/Core/Controls/Controls.cs index 4bfc6c9395..7e76f5925f 100644 --- a/Intersect.Client/Core/Controls/Controls.cs +++ b/Intersect.Client/Core/Controls/Controls.cs @@ -2,202 +2,200 @@ using Intersect.Client.General; using Newtonsoft.Json; -namespace Intersect.Client.Core.Controls +namespace Intersect.Client.Core.Controls; + + +public partial class Controls { - public partial class Controls - { + public readonly IDictionary ControlMapping; - public readonly IDictionary ControlMapping; + public Controls(Controls gameControls = null) + { + ControlMapping = new Dictionary(); - public Controls(Controls gameControls = null) + if (gameControls != null) { - ControlMapping = new Dictionary(); - - if (gameControls != null) + foreach (var mapping in gameControls.ControlMapping) { - foreach (var mapping in gameControls.ControlMapping) - { - CreateControlMap(mapping.Key, mapping.Value); - } + CreateControlMap(mapping.Key, mapping.Value); } - else + } + else + { + ResetDefaults(); + foreach (Control control in Enum.GetValues(typeof(Control))) { - ResetDefaults(); - foreach (Control control in Enum.GetValues(typeof(Control))) - { - MigrateControlBindings(control); + MigrateControlBindings(control); + + var name = Enum.GetName(typeof(Control), control); - var name = Enum.GetName(typeof(Control), control); + if (!ControlMapping.TryGetValue(control, out var controlMapping)) + { + continue; + } - if (!ControlMapping.TryGetValue(control, out var controlMapping)) + var bindings = controlMapping.Bindings; + for (var bindingIndex = 0; bindingIndex < bindings.Count; bindingIndex++) + { + var preferenceKey = $"{name}_binding{bindingIndex}"; + var preference = Globals.Database.LoadPreference(preferenceKey); + if (string.IsNullOrWhiteSpace(preference)) { - continue; + Globals.Database.SavePreference(preferenceKey, JsonConvert.SerializeObject(bindings[bindingIndex])); } - - var bindings = controlMapping.Bindings; - for (var bindingIndex = 0; bindingIndex < bindings.Count; bindingIndex++) + else { - var preferenceKey = $"{name}_binding{bindingIndex}"; - var preference = Globals.Database.LoadPreference(preferenceKey); - if (string.IsNullOrWhiteSpace(preference)) - { - Globals.Database.SavePreference(preferenceKey, JsonConvert.SerializeObject(bindings[bindingIndex])); - } - else - { - bindings[bindingIndex] = JsonConvert.DeserializeObject(preference); - } + bindings[bindingIndex] = JsonConvert.DeserializeObject(preference); } } } } + } - public static Controls ActiveControls { get; set; } + public static Controls ActiveControls { get; set; } - public void ResetDefaults() + public void ResetDefaults() + { + CreateControlMap(Control.MoveUp, new ControlValue(Keys.None, Keys.Up), new ControlValue(Keys.None, Keys.W)); + CreateControlMap(Control.MoveDown, new ControlValue(Keys.None, Keys.Down), new ControlValue(Keys.None, Keys.S)); + CreateControlMap(Control.MoveLeft, new ControlValue(Keys.None, Keys.Left), new ControlValue(Keys.None, Keys.A)); + CreateControlMap(Control.MoveRight, new ControlValue(Keys.None, Keys.Right), new ControlValue(Keys.None, Keys.D)); + CreateControlMap(Control.AttackInteract, new ControlValue(Keys.None, Keys.E), new ControlValue(Keys.None, Keys.LButton)); + CreateControlMap(Control.Block, new ControlValue(Keys.None, Keys.Q), new ControlValue(Keys.None, Keys.RButton)); + CreateControlMap(Control.AutoTarget, new ControlValue(Keys.None, Keys.Tab), ControlValue.Default); + CreateControlMap(Control.PickUp, new ControlValue(Keys.None, Keys.Space), ControlValue.Default); + CreateControlMap(Control.Enter, new ControlValue(Keys.None, Keys.Enter), ControlValue.Default); + CreateControlMap(Control.Hotkey1, new ControlValue(Keys.None, Keys.D1), ControlValue.Default); + CreateControlMap(Control.Hotkey2, new ControlValue(Keys.None, Keys.D2), ControlValue.Default); + CreateControlMap(Control.Hotkey3, new ControlValue(Keys.None, Keys.D3), ControlValue.Default); + CreateControlMap(Control.Hotkey4, new ControlValue(Keys.None, Keys.D4), ControlValue.Default); + CreateControlMap(Control.Hotkey5, new ControlValue(Keys.None, Keys.D5), ControlValue.Default); + CreateControlMap(Control.Hotkey6, new ControlValue(Keys.None, Keys.D6), ControlValue.Default); + CreateControlMap(Control.Hotkey7, new ControlValue(Keys.None, Keys.D7), ControlValue.Default); + CreateControlMap(Control.Hotkey8, new ControlValue(Keys.None, Keys.D8), ControlValue.Default); + CreateControlMap(Control.Hotkey9, new ControlValue(Keys.None, Keys.D9), ControlValue.Default); + CreateControlMap(Control.Hotkey0, new ControlValue(Keys.None, Keys.D0), ControlValue.Default); + CreateControlMap(Control.Screenshot, new ControlValue(Keys.None, Keys.F12), ControlValue.Default); + CreateControlMap(Control.OpenMenu, new ControlValue(Keys.None, Keys.Escape), ControlValue.Default); + CreateControlMap(Control.OpenInventory, new ControlValue(Keys.None, Keys.I), ControlValue.Default); + CreateControlMap(Control.OpenQuests, new ControlValue(Keys.None, Keys.L), ControlValue.Default); + CreateControlMap(Control.OpenCharacterInfo, new ControlValue(Keys.None, Keys.C), ControlValue.Default); + CreateControlMap(Control.OpenParties, new ControlValue(Keys.None, Keys.P), ControlValue.Default); + CreateControlMap(Control.OpenSpells, new ControlValue(Keys.None, Keys.K), ControlValue.Default); + CreateControlMap(Control.OpenFriends, new ControlValue(Keys.None, Keys.F), ControlValue.Default); + CreateControlMap(Control.OpenGuild, new ControlValue(Keys.None, Keys.G), ControlValue.Default); + CreateControlMap(Control.OpenSettings, new ControlValue(Keys.None, Keys.O), ControlValue.Default); + CreateControlMap(Control.OpenDebugger, new ControlValue(Keys.None, Keys.F2), ControlValue.Default); + CreateControlMap(Control.OpenAdminPanel, new ControlValue(Keys.None, Keys.Insert), ControlValue.Default); + CreateControlMap(Control.ToggleGui, new ControlValue(Keys.None, Keys.F11), ControlValue.Default); + CreateControlMap(Control.TurnAround, new ControlValue(Keys.None, Keys.Control), ControlValue.Default); + CreateControlMap(Control.ToggleZoomIn, ControlValue.Default, ControlValue.Default); + CreateControlMap(Control.ToggleZoomOut, ControlValue.Default, ControlValue.Default); + CreateControlMap(Control.HoldToZoomIn, ControlValue.Default, ControlValue.Default); + CreateControlMap(Control.HoldToZoomOut, ControlValue.Default, ControlValue.Default); + CreateControlMap(Control.ToggleFullscreen, new ControlValue(Keys.Alt, Keys.Enter), ControlValue.Default); + // CreateControlMap(Control.Submit, new ControlValue(Keys.None, Keys.Enter), ControlValue.Default); + // CreateControlMap(Control.Cancel, new ControlValue(Keys.None, Keys.Back), ControlValue.Default); + // CreateControlMap(Control.Next, new ControlValue(Keys.None, Keys.Tab), ControlValue.Default); + // CreateControlMap(Control.Previous, new ControlValue(Keys.Shift, Keys.Tab), ControlValue.Default); + } + + private static void MigrateControlBindings(Control control) + { + var name = Enum.GetName(typeof(Control), control); + if (Globals.Database.HasPreference($"{name}_key1value")) { - CreateControlMap(Control.MoveUp, new ControlValue(Keys.None, Keys.Up), new ControlValue(Keys.None, Keys.W)); - CreateControlMap(Control.MoveDown, new ControlValue(Keys.None, Keys.Down), new ControlValue(Keys.None, Keys.S)); - CreateControlMap(Control.MoveLeft, new ControlValue(Keys.None, Keys.Left), new ControlValue(Keys.None, Keys.A)); - CreateControlMap(Control.MoveRight, new ControlValue(Keys.None, Keys.Right), new ControlValue(Keys.None, Keys.D)); - CreateControlMap(Control.AttackInteract, new ControlValue(Keys.None, Keys.E), new ControlValue(Keys.None, Keys.LButton)); - CreateControlMap(Control.Block, new ControlValue(Keys.None, Keys.Q), new ControlValue(Keys.None, Keys.RButton)); - CreateControlMap(Control.AutoTarget, new ControlValue(Keys.None, Keys.Tab), ControlValue.Default); - CreateControlMap(Control.PickUp, new ControlValue(Keys.None, Keys.Space), ControlValue.Default); - CreateControlMap(Control.Enter, new ControlValue(Keys.None, Keys.Enter), ControlValue.Default); - CreateControlMap(Control.Hotkey1, new ControlValue(Keys.None, Keys.D1), ControlValue.Default); - CreateControlMap(Control.Hotkey2, new ControlValue(Keys.None, Keys.D2), ControlValue.Default); - CreateControlMap(Control.Hotkey3, new ControlValue(Keys.None, Keys.D3), ControlValue.Default); - CreateControlMap(Control.Hotkey4, new ControlValue(Keys.None, Keys.D4), ControlValue.Default); - CreateControlMap(Control.Hotkey5, new ControlValue(Keys.None, Keys.D5), ControlValue.Default); - CreateControlMap(Control.Hotkey6, new ControlValue(Keys.None, Keys.D6), ControlValue.Default); - CreateControlMap(Control.Hotkey7, new ControlValue(Keys.None, Keys.D7), ControlValue.Default); - CreateControlMap(Control.Hotkey8, new ControlValue(Keys.None, Keys.D8), ControlValue.Default); - CreateControlMap(Control.Hotkey9, new ControlValue(Keys.None, Keys.D9), ControlValue.Default); - CreateControlMap(Control.Hotkey0, new ControlValue(Keys.None, Keys.D0), ControlValue.Default); - CreateControlMap(Control.Screenshot, new ControlValue(Keys.None, Keys.F12), ControlValue.Default); - CreateControlMap(Control.OpenMenu, new ControlValue(Keys.None, Keys.Escape), ControlValue.Default); - CreateControlMap(Control.OpenInventory, new ControlValue(Keys.None, Keys.I), ControlValue.Default); - CreateControlMap(Control.OpenQuests, new ControlValue(Keys.None, Keys.L), ControlValue.Default); - CreateControlMap(Control.OpenCharacterInfo, new ControlValue(Keys.None, Keys.C), ControlValue.Default); - CreateControlMap(Control.OpenParties, new ControlValue(Keys.None, Keys.P), ControlValue.Default); - CreateControlMap(Control.OpenSpells, new ControlValue(Keys.None, Keys.K), ControlValue.Default); - CreateControlMap(Control.OpenFriends, new ControlValue(Keys.None, Keys.F), ControlValue.Default); - CreateControlMap(Control.OpenGuild, new ControlValue(Keys.None, Keys.G), ControlValue.Default); - CreateControlMap(Control.OpenSettings, new ControlValue(Keys.None, Keys.O), ControlValue.Default); - CreateControlMap(Control.OpenDebugger, new ControlValue(Keys.None, Keys.F2), ControlValue.Default); - CreateControlMap(Control.OpenAdminPanel, new ControlValue(Keys.None, Keys.Insert), ControlValue.Default); - CreateControlMap(Control.ToggleGui, new ControlValue(Keys.None, Keys.F11), ControlValue.Default); - CreateControlMap(Control.TurnAround, new ControlValue(Keys.None, Keys.Control), ControlValue.Default); - CreateControlMap(Control.ToggleZoomIn, ControlValue.Default, ControlValue.Default); - CreateControlMap(Control.ToggleZoomOut, ControlValue.Default, ControlValue.Default); - CreateControlMap(Control.HoldToZoomIn, ControlValue.Default, ControlValue.Default); - CreateControlMap(Control.HoldToZoomOut, ControlValue.Default, ControlValue.Default); - CreateControlMap(Control.ToggleFullscreen, new ControlValue(Keys.Alt, Keys.Enter), ControlValue.Default); - // CreateControlMap(Control.Submit, new ControlValue(Keys.None, Keys.Enter), ControlValue.Default); - // CreateControlMap(Control.Cancel, new ControlValue(Keys.None, Keys.Back), ControlValue.Default); - // CreateControlMap(Control.Next, new ControlValue(Keys.None, Keys.Tab), ControlValue.Default); - // CreateControlMap(Control.Previous, new ControlValue(Keys.Shift, Keys.Tab), ControlValue.Default); + Globals.Database.SavePreference($"{name}_binding0", Globals.Database.LoadPreference($"{name}_key1value")); + Globals.Database.SavePreference($"{name}_binding1", Globals.Database.LoadPreference($"{name}_key2value")); + Globals.Database.DeletePreference($"{name}_key1value"); + Globals.Database.DeletePreference($"{name}_key2value"); } - - private static void MigrateControlBindings(Control control) + else if (Globals.Database.HasPreference($"{name}_key1")) { - var name = Enum.GetName(typeof(Control), control); - if (Globals.Database.HasPreference($"{name}_key1value")) - { - Globals.Database.SavePreference($"{name}_binding0", Globals.Database.LoadPreference($"{name}_key1value")); - Globals.Database.SavePreference($"{name}_binding1", Globals.Database.LoadPreference($"{name}_key2value")); - Globals.Database.DeletePreference($"{name}_key1value"); - Globals.Database.DeletePreference($"{name}_key2value"); - } - else if (Globals.Database.HasPreference($"{name}_key1")) - { - var key1 = JsonConvert.DeserializeObject(Globals.Database.LoadPreference($"{name}_key1")); - var key2 = JsonConvert.DeserializeObject(Globals.Database.LoadPreference($"{name}_key2")); - Globals.Database.SavePreference($"{name}_binding0", JsonConvert.SerializeObject(new ControlValue(Keys.None, key1))); - Globals.Database.SavePreference($"{name}_binding1", JsonConvert.SerializeObject(new ControlValue(Keys.None, key2))); - Globals.Database.DeletePreference($"{name}_key1"); - Globals.Database.DeletePreference($"{name}_key2"); - } + var key1 = JsonConvert.DeserializeObject(Globals.Database.LoadPreference($"{name}_key1")); + var key2 = JsonConvert.DeserializeObject(Globals.Database.LoadPreference($"{name}_key2")); + Globals.Database.SavePreference($"{name}_binding0", JsonConvert.SerializeObject(new ControlValue(Keys.None, key1))); + Globals.Database.SavePreference($"{name}_binding1", JsonConvert.SerializeObject(new ControlValue(Keys.None, key2))); + Globals.Database.DeletePreference($"{name}_key1"); + Globals.Database.DeletePreference($"{name}_key2"); } + } - public void Save() + public void Save() + { + foreach (Control control in Enum.GetValues(typeof(Control))) { - foreach (Control control in Enum.GetValues(typeof(Control))) + var name = Enum.GetName(typeof(Control), control); + var bindings = ControlMapping[control].Bindings; + for (var bindingIndex = 0; bindingIndex < bindings.Count; bindingIndex++) { - var name = Enum.GetName(typeof(Control), control); - var bindings = ControlMapping[control].Bindings; - for (var bindingIndex = 0; bindingIndex < bindings.Count; bindingIndex++) - { - var preferenceKey = $"{name}_binding{bindingIndex}"; - Globals.Database.SavePreference(preferenceKey, JsonConvert.SerializeObject(bindings[bindingIndex])); - } + var preferenceKey = $"{name}_binding{bindingIndex}"; + Globals.Database.SavePreference(preferenceKey, JsonConvert.SerializeObject(bindings[bindingIndex])); } } + } + + public static void Init() + { + ActiveControls = new Controls(); + } - public static void Init() + public static bool KeyDown(Control control) + { + if (ActiveControls?.ControlMapping.ContainsKey(control) ?? false) { - ActiveControls = new Controls(); + return ActiveControls.ControlMapping[control]?.KeyDown() ?? false; } - public static bool KeyDown(Control control) - { - if (ActiveControls?.ControlMapping.ContainsKey(control) ?? false) - { - return ActiveControls.ControlMapping[control]?.KeyDown() ?? false; - } + return false; + } - return false; - } + public static List GetControlsFor(Keys modifier, Keys key) + { + return Enum.GetValues(typeof(Control)) + .Cast() + .Where(control => ControlHasKey(control, modifier, key)) + .ToList(); + } - public static List GetControlsFor(Keys modifier, Keys key) + public static bool ControlHasKey(Control control, Keys modifier, Keys key) + { + if (key == Keys.None) { - return Enum.GetValues(typeof(Control)) - .Cast() - .Where(control => ControlHasKey(control, modifier, key)) - .ToList(); + return false; } - public static bool ControlHasKey(Control control, Keys modifier, Keys key) + if (!(ActiveControls?.ControlMapping.ContainsKey(control) ?? false)) { - if (key == Keys.None) - { - return false; - } - - if (!(ActiveControls?.ControlMapping.ContainsKey(control) ?? false)) - { - return false; - } - - var mapping = ActiveControls.ControlMapping[control]; - - return mapping?.Bindings.Any(binding => binding.Modifier == modifier && binding.Key == key) ?? false; + return false; } - public void UpdateControl(Control control, int keyNum, Keys modifier, Keys key) - { - var mapping = ControlMapping[control]; - if (mapping == null) - { - return; - } + var mapping = ActiveControls.ControlMapping[control]; - mapping.Bindings[keyNum].Modifier = modifier; - mapping.Bindings[keyNum].Key = key; - } + return mapping?.Bindings.Any(binding => binding.Modifier == modifier && binding.Key == key) ?? false; + } - private void CreateControlMap(Control control, ControlValue binding, params ControlValue[] alternateBindings) + public void UpdateControl(Control control, int keyNum, Keys modifier, Keys key) + { + var mapping = ControlMapping[control]; + if (mapping == null) { - ControlMapping[control] = new ControlMap(binding, alternateBindings); + return; } - private void CreateControlMap(Control control, ControlMap controlMap) - { - ControlMapping[control] = new ControlMap(controlMap); - } + mapping.Bindings[keyNum].Modifier = modifier; + mapping.Bindings[keyNum].Key = key; + } + private void CreateControlMap(Control control, ControlValue binding, params ControlValue[] alternateBindings) + { + ControlMapping[control] = new ControlMap(binding, alternateBindings); + } + + private void CreateControlMap(Control control, ControlMap controlMap) + { + ControlMapping[control] = new ControlMap(controlMap); } } diff --git a/Intersect.Client/Core/Fade.cs b/Intersect.Client/Core/Fade.cs index b6747e64b3..649e39c2e5 100644 --- a/Intersect.Client/Core/Fade.cs +++ b/Intersect.Client/Core/Fade.cs @@ -1,101 +1,99 @@ using Intersect.Client.Networking; using Intersect.Utilities; -namespace Intersect.Client.Core +namespace Intersect.Client.Core; + + +public static partial class Fade { - public static partial class Fade + public enum FadeType { - public enum FadeType - { + None = 0, - None = 0, + In = 1, - In = 1, + Out = 2, - Out = 2, - - } + } - private static FadeType sCurrentAction; + private static FadeType sCurrentAction; - private static float sFadeAmt; + private static float sFadeAmt; - private static float sFadeDurationMs; + private static float sFadeDurationMs; - private static long sLastUpdate; + private static long sLastUpdate; - public static float Alpha => sFadeAmt * 255f; + public static float Alpha => sFadeAmt * 255f; - private static bool InformServer { get; set; } + private static bool InformServer { get; set; } - public static void FadeIn(float durationMs, bool informServer = false) - { - sFadeDurationMs = durationMs; - sCurrentAction = FadeType.In; - sFadeAmt = 1f; - sLastUpdate = Timing.Global.MillisecondsUtc; - InformServer = informServer; - } + public static void FadeIn(float durationMs, bool informServer = false) + { + sFadeDurationMs = durationMs; + sCurrentAction = FadeType.In; + sFadeAmt = 1f; + sLastUpdate = Timing.Global.MillisecondsUtc; + InformServer = informServer; + } - public static void FadeOut(float durationMs, bool informServer = false) - { - sFadeDurationMs = durationMs; - sCurrentAction = FadeType.Out; - sFadeAmt = 0f; - sLastUpdate = Timing.Global.MillisecondsUtc; - InformServer = informServer; - } + public static void FadeOut(float durationMs, bool informServer = false) + { + sFadeDurationMs = durationMs; + sCurrentAction = FadeType.Out; + sFadeAmt = 0f; + sLastUpdate = Timing.Global.MillisecondsUtc; + InformServer = informServer; + } - public static void Cancel(bool informServer = false) - { - sCurrentAction = FadeType.None; - sFadeAmt = default; - InformServerOfCompletion(true); - } + public static void Cancel(bool informServer = false) + { + sCurrentAction = FadeType.None; + sFadeAmt = default; + InformServerOfCompletion(true); + } - public static bool DoneFading() - { - return sCurrentAction == FadeType.None; - } + public static bool DoneFading() + { + return sCurrentAction == FadeType.None; + } - public static void Update() + public static void Update() + { + if (sCurrentAction == FadeType.In) { - if (sCurrentAction == FadeType.In) - { - sFadeAmt -= (Timing.Global.MillisecondsUtc - sLastUpdate) / sFadeDurationMs; - if (sFadeAmt <= 0f) - { - sCurrentAction = FadeType.None; - sFadeAmt = 0f; - - InformServerOfCompletion(); - } - } - else if (sCurrentAction == FadeType.Out) + sFadeAmt -= (Timing.Global.MillisecondsUtc - sLastUpdate) / sFadeDurationMs; + if (sFadeAmt <= 0f) { - sFadeAmt += (Timing.Global.MillisecondsUtc - sLastUpdate) / sFadeDurationMs; - if (sFadeAmt >= 1) - { - sCurrentAction = FadeType.None; - sFadeAmt = 1f; - - InformServerOfCompletion(); - } - } + sCurrentAction = FadeType.None; + sFadeAmt = 0f; - sLastUpdate = Timing.Global.MillisecondsUtc; + InformServerOfCompletion(); + } } - - private static void InformServerOfCompletion(bool force = false) + else if (sCurrentAction == FadeType.Out) { - if (InformServer || force) + sFadeAmt += (Timing.Global.MillisecondsUtc - sLastUpdate) / sFadeDurationMs; + if (sFadeAmt >= 1) { - InformServer = false; - PacketSender.SendFadeCompletePacket(); + sCurrentAction = FadeType.None; + sFadeAmt = 1f; + + InformServerOfCompletion(); } } + + sLastUpdate = Timing.Global.MillisecondsUtc; } + private static void InformServerOfCompletion(bool force = false) + { + if (InformServer || force) + { + InformServer = false; + PacketSender.SendFadeCompletePacket(); + } + } } diff --git a/Intersect.Client/Core/Graphics.cs b/Intersect.Client/Core/Graphics.cs index cce720bd86..97d527155b 100644 --- a/Intersect.Client/Core/Graphics.cs +++ b/Intersect.Client/Core/Graphics.cs @@ -11,618 +11,637 @@ using Intersect.GameObjects; using Intersect.Utilities; -namespace Intersect.Client.Core -{ +namespace Intersect.Client.Core; - public static partial class Graphics - { - public static GameFont ActionMsgFont; +public static partial class Graphics +{ + + public static GameFont ActionMsgFont; - public static object AnimationLock = new object(); + public static object AnimationLock = new object(); - //Darkness Stuff - public static float BrightnessLevel; + //Darkness Stuff + public static float BrightnessLevel; - public static GameFont ChatBubbleFont; + public static GameFont ChatBubbleFont; - private static FloatRect _currentView; + private static FloatRect _currentView; - public static FloatRect CurrentView + public static FloatRect CurrentView + { + get => _currentView; + set { - get => _currentView; - set - { - _currentView = value; - Renderer.SetView(_currentView); - } + _currentView = value; + Renderer.SetView(_currentView); } - - public static FloatRect WorldViewport => new FloatRect(CurrentView.Position, CurrentView.Size / (Globals.Database?.WorldZoom ?? 1)); + } + + public static FloatRect WorldViewport => new FloatRect(CurrentView.Position, CurrentView.Size / (Globals.Database?.WorldZoom ?? 1)); - public static GameShader DefaultShader; + public static GameShader DefaultShader; - //Rendering Variables - private static GameTexture sMenuBackground; + //Rendering Variables + private static GameTexture sMenuBackground; - public static int DrawCalls; + public static int DrawCalls; - public static int EntitiesDrawn; + public static int EntitiesDrawn; - public static GameFont EntityNameFont; + public static GameFont EntityNameFont; - //Screen Values - public static GameFont GameFont; + //Screen Values + public static GameFont GameFont; - public static object GfxLock = new object(); + public static object GfxLock = new object(); - //Grid Switched - public static bool GridSwitched; + //Grid Switched + public static bool GridSwitched; - public static int LightsDrawn; + public static int LightsDrawn; - //Animations - public static List LiveAnimations = new List(); + //Animations + public static List LiveAnimations = new List(); - public static int MapsDrawn; + public static int MapsDrawn; - private static int sMenuBackgroundIndex; + private static int sMenuBackgroundIndex; - private static long sMenuBackgroundInterval; + private static long sMenuBackgroundInterval; - //Overlay Stuff - public static Color OverlayColor = Color.Transparent; + //Overlay Stuff + public static Color OverlayColor = Color.Transparent; - public static ColorF PlayerLightColor = ColorF.White; + public static ColorF PlayerLightColor = ColorF.White; - //Game Renderer - public static GameRenderer Renderer; + //Game Renderer + public static GameRenderer Renderer; - //Cache the Y based rendering - public static HashSet[,] RenderingEntities; + //Cache the Y based rendering + public static HashSet[,] RenderingEntities; - private static GameContentManager sContentManager; + private static GameContentManager sContentManager; - private static GameRenderTexture sDarknessTexture; + private static GameRenderTexture sDarknessTexture; - private static long sFadeTimer; + private static long sFadeTimer; - private static List sLightQueue = new List(); + private static List sLightQueue = new List(); - //Player Spotlight Values - private static long sLightUpdate; + //Player Spotlight Values + private static long sLightUpdate; - private static int sOldHeight; + private static int sOldHeight; - //Resolution - private static int sOldWidth; + //Resolution + private static int sOldWidth; - private static long sOverlayUpdate; + private static long sOverlayUpdate; - private static float sPlayerLightExpand; + private static float sPlayerLightExpand; - private static float sPlayerLightIntensity = 255; + private static float sPlayerLightIntensity = 255; - private static float sPlayerLightSize; + private static float sPlayerLightSize; - public static GameFont UIFont; + public static GameFont UIFont; - public static float BaseWorldScale => Options.Instance?.MapOpts?.TileScale ?? 1; + public static float BaseWorldScale => Options.Instance?.MapOpts?.TileScale ?? 1; - //Init Functions - public static void InitGraphics() + //Init Functions + public static void InitGraphics() + { + Renderer.Init(); + sContentManager = Globals.ContentManager; + sContentManager.LoadAll(); + GameFont = FindFont(ClientConfiguration.Instance.GameFont); + UIFont = FindFont(ClientConfiguration.Instance.UIFont); + EntityNameFont = FindFont(ClientConfiguration.Instance.EntityNameFont); + ChatBubbleFont = FindFont(ClientConfiguration.Instance.ChatBubbleFont); + ActionMsgFont = FindFont(ClientConfiguration.Instance.ActionMsgFont); + } + + public static GameFont FindFont(string font) + { + var size = 8; + + if (font.IndexOf(',') > -1) { - Renderer.Init(); - sContentManager = Globals.ContentManager; - sContentManager.LoadAll(); - GameFont = FindFont(ClientConfiguration.Instance.GameFont); - UIFont = FindFont(ClientConfiguration.Instance.UIFont); - EntityNameFont = FindFont(ClientConfiguration.Instance.EntityNameFont); - ChatBubbleFont = FindFont(ClientConfiguration.Instance.ChatBubbleFont); - ActionMsgFont = FindFont(ClientConfiguration.Instance.ActionMsgFont); + var parts = font.Split(','); + font = parts[0]; + int.TryParse(parts[1], out size); } - public static GameFont FindFont(string font) - { - var size = 8; + return sContentManager.GetFont(font, size); + } - if (font.IndexOf(',') > -1) + public static void InitInGame() + { + RenderingEntities = new HashSet[6, Options.MapHeight * 5]; + for (var z = 0; z < 6; z++) + { + for (var i = 0; i < Options.MapHeight * 5; i++) { - var parts = font.Split(','); - font = parts[0]; - int.TryParse(parts[1], out size); + RenderingEntities[z, i] = new HashSet(); } - - return sContentManager.GetFont(font, size); } + } + + public static void DrawIntro() + { + var imageTex = sContentManager.GetTexture( + Framework.Content.TextureType.Image, ClientConfiguration.Instance.IntroImages[Globals.IntroIndex] + ); - public static void InitInGame() + if (imageTex != null) { - RenderingEntities = new HashSet[6, Options.MapHeight * 5]; - for (var z = 0; z < 6; z++) - { - for (var i = 0; i < Options.MapHeight * 5; i++) - { - RenderingEntities[z, i] = new HashSet(); - } - } + DrawFullScreenTextureFitMinimum(imageTex); } + } - public static void DrawIntro() + private static void DrawMenu() + { + // No background in the main menu. + if (ClientConfiguration.Instance.MenuBackground.Count == 0) { - var imageTex = sContentManager.GetTexture( - Framework.Content.TextureType.Image, ClientConfiguration.Instance.IntroImages[Globals.IntroIndex] - ); - - if (imageTex != null) - { - DrawFullScreenTextureFitMinimum(imageTex); - } + return; } - private static void DrawMenu() + // Animated background in the main menu. + if (ClientConfiguration.Instance.MenuBackground.Count > 1) { - // No background in the main menu. - if (ClientConfiguration.Instance.MenuBackground.Count == 0) + sMenuBackground = sContentManager.GetTexture( + TextureType.Gui, ClientConfiguration.Instance.MenuBackground[sMenuBackgroundIndex] + ); + + if (sMenuBackground == null) { return; } - // Animated background in the main menu. - if (ClientConfiguration.Instance.MenuBackground.Count > 1) - { - sMenuBackground = sContentManager.GetTexture( - TextureType.Gui, ClientConfiguration.Instance.MenuBackground[sMenuBackgroundIndex] - ); - - if (sMenuBackground == null) - { - return; - } - - var currentTimeMs = Timing.Global.MillisecondsUtc; + var currentTimeMs = Timing.Global.MillisecondsUtc; - if (sMenuBackgroundInterval < currentTimeMs) - { - sMenuBackgroundIndex = - (sMenuBackgroundIndex + 1) % ClientConfiguration.Instance.MenuBackground.Count; + if (sMenuBackgroundInterval < currentTimeMs) + { + sMenuBackgroundIndex = + (sMenuBackgroundIndex + 1) % ClientConfiguration.Instance.MenuBackground.Count; - sMenuBackgroundInterval = currentTimeMs + ClientConfiguration.Instance.MenuBackgroundFrameInterval; - } + sMenuBackgroundInterval = currentTimeMs + ClientConfiguration.Instance.MenuBackgroundFrameInterval; } + } - // Static background in the main menu. - else - { - sMenuBackground = sContentManager.GetTexture( - TextureType.Gui, ClientConfiguration.Instance.MenuBackground[0] - ); + // Static background in the main menu. + else + { + sMenuBackground = sContentManager.GetTexture( + TextureType.Gui, ClientConfiguration.Instance.MenuBackground[0] + ); - if (sMenuBackground == null) - { - return; - } + if (sMenuBackground == null) + { + return; } + } - // Switch between the preferred display mode, then render the fullscreen texture. - switch (ClientConfiguration.Instance.MenuBackgroundDisplayMode) - { - case DisplayMode.Default: - DrawFullScreenTexture(sMenuBackground); - break; + // Switch between the preferred display mode, then render the fullscreen texture. + switch (ClientConfiguration.Instance.MenuBackgroundDisplayMode) + { + case DisplayMode.Default: + DrawFullScreenTexture(sMenuBackground); + break; - case DisplayMode.Center: - DrawFullScreenTextureCentered(sMenuBackground); - break; + case DisplayMode.Center: + DrawFullScreenTextureCentered(sMenuBackground); + break; - case DisplayMode.Stretch: - DrawFullScreenTextureStretched(sMenuBackground); - break; + case DisplayMode.Stretch: + DrawFullScreenTextureStretched(sMenuBackground); + break; - case DisplayMode.FitHeight: - DrawFullScreenTextureFitHeight(sMenuBackground); - break; + case DisplayMode.FitHeight: + DrawFullScreenTextureFitHeight(sMenuBackground); + break; - case DisplayMode.FitWidth: - DrawFullScreenTextureFitWidth(sMenuBackground); - break; + case DisplayMode.FitWidth: + DrawFullScreenTextureFitWidth(sMenuBackground); + break; - case DisplayMode.Fit: - DrawFullScreenTextureFitMaximum(sMenuBackground); - break; + case DisplayMode.Fit: + DrawFullScreenTextureFitMaximum(sMenuBackground); + break; - case DisplayMode.Cover: - DrawFullScreenTextureFitMinimum(sMenuBackground); - break; - } + case DisplayMode.Cover: + DrawFullScreenTextureFitMinimum(sMenuBackground); + break; } + } - public static void DrawInGame(TimeSpan deltaTime) + public static void DrawInGame(TimeSpan deltaTime) + { + var currentMap = Globals.Me.MapInstance as MapInstance; + if (currentMap == null) { - var currentMap = Globals.Me.MapInstance as MapInstance; - if (currentMap == null) - { - return; - } + return; + } - if (Globals.NeedsMaps) - { - return; - } + if (Globals.NeedsMaps) + { + return; + } - if (GridSwitched) - { - //Brightness - var brightnessTarget = (byte)(currentMap.Brightness / 100f * 255); - BrightnessLevel = brightnessTarget; - PlayerLightColor.R = currentMap.PlayerLightColor.R; - PlayerLightColor.G = currentMap.PlayerLightColor.G; - PlayerLightColor.B = currentMap.PlayerLightColor.B; - sPlayerLightSize = currentMap.PlayerLightSize; - sPlayerLightIntensity = currentMap.PlayerLightIntensity; - sPlayerLightExpand = currentMap.PlayerLightExpand; - - //Overlay - OverlayColor.A = (byte)currentMap.AHue; - OverlayColor.R = (byte)currentMap.RHue; - OverlayColor.G = (byte)currentMap.GHue; - OverlayColor.B = (byte)currentMap.BHue; - - //Fog && Panorama - currentMap.GridSwitched(); - GridSwitched = false; - } + if (GridSwitched) + { + //Brightness + var brightnessTarget = (byte)(currentMap.Brightness / 100f * 255); + BrightnessLevel = brightnessTarget; + PlayerLightColor.R = currentMap.PlayerLightColor.R; + PlayerLightColor.G = currentMap.PlayerLightColor.G; + PlayerLightColor.B = currentMap.PlayerLightColor.B; + sPlayerLightSize = currentMap.PlayerLightSize; + sPlayerLightIntensity = currentMap.PlayerLightIntensity; + sPlayerLightExpand = currentMap.PlayerLightExpand; + + //Overlay + OverlayColor.A = (byte)currentMap.AHue; + OverlayColor.R = (byte)currentMap.RHue; + OverlayColor.G = (byte)currentMap.GHue; + OverlayColor.B = (byte)currentMap.BHue; + + //Fog && Panorama + currentMap.GridSwitched(); + GridSwitched = false; + } - var animations = LiveAnimations.ToArray(); - foreach (var animInstance in animations) + var animations = LiveAnimations.ToArray(); + foreach (var animInstance in animations) + { + if (animInstance.ParentGone()) { - if (animInstance.ParentGone()) - { - animInstance.Dispose(); - } + animInstance.Dispose(); } + } - // Clear our previous darkness texture. - ClearDarknessTexture(); + // Clear our previous darkness texture. + ClearDarknessTexture(); - var gridX = currentMap.GridX; - var gridY = currentMap.GridY; + var gridX = currentMap.GridX; + var gridY = currentMap.GridY; - //Draw Panoramas First... - for (var x = gridX - 1; x <= gridX + 1; x++) + //Draw Panoramas First... + for (var x = gridX - 1; x <= gridX + 1; x++) + { + for (var y = gridY - 1; y <= gridY + 1; y++) { - for (var y = gridY - 1; y <= gridY + 1; y++) + if (x >= 0 && + x < Globals.MapGridWidth && + y >= 0 && + y < Globals.MapGridHeight && + Globals.MapGrid[x, y] != Guid.Empty) { - if (x >= 0 && - x < Globals.MapGridWidth && - y >= 0 && - y < Globals.MapGridHeight && - Globals.MapGrid[x, y] != Guid.Empty) - { - DrawMapPanorama(Globals.MapGrid[x, y]); - } + DrawMapPanorama(Globals.MapGrid[x, y]); } } + } - for (var x = gridX - 1; x <= gridX + 1; x++) + for (var x = gridX - 1; x <= gridX + 1; x++) + { + for (var y = gridY - 1; y <= gridY + 1; y++) { - for (var y = gridY - 1; y <= gridY + 1; y++) + if (x >= 0 && + x < Globals.MapGridWidth && + y >= 0 && + y < Globals.MapGridHeight && + Globals.MapGrid[x, y] != Guid.Empty) { - if (x >= 0 && - x < Globals.MapGridWidth && - y >= 0 && - y < Globals.MapGridHeight && - Globals.MapGrid[x, y] != Guid.Empty) - { - DrawMap(Globals.MapGrid[x, y], 0); - } + DrawMap(Globals.MapGrid[x, y], 0); } } + } - // Handle our plugin drawing. - Globals.OnGameDraw(DrawStates.GroundLayers, deltaTime); + // Handle our plugin drawing. + Globals.OnGameDraw(DrawStates.GroundLayers, deltaTime); - foreach (var animInstance in animations) - { - animInstance.Draw(false); - } + foreach (var animInstance in animations) + { + animInstance.Draw(false); + } - // Handle our plugin drawing. - Globals.OnGameDraw(DrawStates.BelowPlayer, deltaTime); + // Handle our plugin drawing. + Globals.OnGameDraw(DrawStates.BelowPlayer, deltaTime); - for (var y = 0; y < Options.MapHeight * 5; y++) + for (var y = 0; y < Options.MapHeight * 5; y++) + { + for (var x = 0; x < 3; x++) { - for (var x = 0; x < 3; x++) + foreach (var entity in RenderingEntities[x, y]) { - foreach (var entity in RenderingEntities[x, y]) - { - // Handle our plugin drawing. - Globals.OnGameDraw(DrawStates.BeforeEntity, entity, deltaTime); + // Handle our plugin drawing. + Globals.OnGameDraw(DrawStates.BeforeEntity, entity, deltaTime); - entity.Draw(); + entity.Draw(); - // Handle our plugin drawing. - Globals.OnGameDraw(DrawStates.AfterEntity, entity, deltaTime); + // Handle our plugin drawing. + Globals.OnGameDraw(DrawStates.AfterEntity, entity, deltaTime); - EntitiesDrawn++; - } + EntitiesDrawn++; + } - if (x == 0 && y > 0 && y % Options.MapHeight == 0) + if (x == 0 && y > 0 && y % Options.MapHeight == 0) + { + for (var x1 = gridX - 1; x1 <= gridX + 1; x1++) { - for (var x1 = gridX - 1; x1 <= gridX + 1; x1++) + var y1 = gridY - 2 + (int)Math.Floor(y / (float)Options.MapHeight); + if (x1 >= 0 && + x1 < Globals.MapGridWidth && + y1 >= 0 && + y1 < Globals.MapGridHeight && + Globals.MapGrid[x1, y1] != Guid.Empty) { - var y1 = gridY - 2 + (int)Math.Floor(y / (float)Options.MapHeight); - if (x1 >= 0 && - x1 < Globals.MapGridWidth && - y1 >= 0 && - y1 < Globals.MapGridHeight && - Globals.MapGrid[x1, y1] != Guid.Empty) + var map = MapInstance.Get(Globals.MapGrid[x1, y1]); + if (map != null) { - var map = MapInstance.Get(Globals.MapGrid[x1, y1]); - if (map != null) - { - map.DrawItemsAndLights(); - } + map.DrawItemsAndLights(); } } } } } + } - foreach (var animInstance in animations) - { - animInstance.Draw(false, true); - animInstance.Draw(true, true); - } + foreach (var animInstance in animations) + { + animInstance.Draw(false, true); + animInstance.Draw(true, true); + } - for (var x = gridX - 1; x <= gridX + 1; x++) + for (var x = gridX - 1; x <= gridX + 1; x++) + { + for (var y = gridY - 1; y <= gridY + 1; y++) { - for (var y = gridY - 1; y <= gridY + 1; y++) + if (x >= 0 && + x < Globals.MapGridWidth && + y >= 0 && + y < Globals.MapGridHeight && + Globals.MapGrid[x, y] != Guid.Empty) { - if (x >= 0 && - x < Globals.MapGridWidth && - y >= 0 && - y < Globals.MapGridHeight && - Globals.MapGrid[x, y] != Guid.Empty) - { - DrawMap(Globals.MapGrid[x, y], 1); - } + DrawMap(Globals.MapGrid[x, y], 1); } } + } - for (var y = 0; y < Options.MapHeight * 5; y++) + for (var y = 0; y < Options.MapHeight * 5; y++) + { + for (var x = 3; x < 6; x++) { - for (var x = 3; x < 6; x++) + foreach (var entity in RenderingEntities[x, y]) { - foreach (var entity in RenderingEntities[x, y]) - { - // Handle our plugin drawing. - Globals.OnGameDraw(DrawStates.BeforeEntity, entity, deltaTime); + // Handle our plugin drawing. + Globals.OnGameDraw(DrawStates.BeforeEntity, entity, deltaTime); - entity.Draw(); + entity.Draw(); - // Handle our plugin drawing. - Globals.OnGameDraw(DrawStates.AfterEntity, entity, deltaTime); + // Handle our plugin drawing. + Globals.OnGameDraw(DrawStates.AfterEntity, entity, deltaTime); - EntitiesDrawn++; - } + EntitiesDrawn++; } } + } - // Handle our plugin drawing. - Globals.OnGameDraw(DrawStates.AbovePlayer, deltaTime); + // Handle our plugin drawing. + Globals.OnGameDraw(DrawStates.AbovePlayer, deltaTime); - for (var x = gridX - 1; x <= gridX + 1; x++) + for (var x = gridX - 1; x <= gridX + 1; x++) + { + for (var y = gridY - 1; y <= gridY + 1; y++) { - for (var y = gridY - 1; y <= gridY + 1; y++) + if (x >= 0 && + x < Globals.MapGridWidth && + y >= 0 && + y < Globals.MapGridHeight && + Globals.MapGrid[x, y] != Guid.Empty) { - if (x >= 0 && - x < Globals.MapGridWidth && - y >= 0 && - y < Globals.MapGridHeight && - Globals.MapGrid[x, y] != Guid.Empty) - { - DrawMap(Globals.MapGrid[x, y], 2); - } + DrawMap(Globals.MapGrid[x, y], 2); } } - // Handle our plugin drawing. - Globals.OnGameDraw(DrawStates.FringeLayers, deltaTime); + } + // Handle our plugin drawing. + Globals.OnGameDraw(DrawStates.FringeLayers, deltaTime); - foreach (var animInstance in animations) - { - animInstance.Draw(true); - } + foreach (var animInstance in animations) + { + animInstance.Draw(true); + } - for (var x = gridX - 1; x <= gridX + 1; x++) + for (var x = gridX - 1; x <= gridX + 1; x++) + { + for (var y = gridY - 1; y <= gridY + 1; y++) { - for (var y = gridY - 1; y <= gridY + 1; y++) + if (x >= 0 && + x < Globals.MapGridWidth && + y >= 0 && + y < Globals.MapGridHeight && + Globals.MapGrid[x, y] != Guid.Empty) { - if (x >= 0 && - x < Globals.MapGridWidth && - y >= 0 && - y < Globals.MapGridHeight && - Globals.MapGrid[x, y] != Guid.Empty) + var map = MapInstance.Get(Globals.MapGrid[x, y]); + if (map != null) { - var map = MapInstance.Get(Globals.MapGrid[x, y]); - if (map != null) - { - map.DrawWeather(); - map.DrawFog(); - map.DrawOverlayGraphic(); - map.DrawItemNames(); - } + map.DrawWeather(); + map.DrawFog(); + map.DrawOverlayGraphic(); + map.DrawItemNames(); } } } + } - //Draw the players targets - Globals.Me.DrawTargets(); + //Draw the players targets + Globals.Me.DrawTargets(); - DrawOverlay(); + DrawOverlay(); - // Draw lighting effects. - GenerateLightMap(); - DrawDarkness(); + // Draw lighting effects. + GenerateLightMap(); + DrawDarkness(); - for (var y = 0; y < Options.MapHeight * 5; y++) + for (var y = 0; y < Options.MapHeight * 5; y++) + { + for (var x = 0; x < 3; x++) { - for (var x = 0; x < 3; x++) + foreach (var entity in RenderingEntities[x, y]) { - foreach (var entity in RenderingEntities[x, y]) + entity.DrawName(null); + if (entity.GetType() != typeof(Event)) { - entity.DrawName(null); - if (entity.GetType() != typeof(Event)) - { - entity.DrawHpBar(); - entity.DrawCastingBar(); - } - - entity.DrawChatBubbles(); + entity.DrawHpBar(); + entity.DrawCastingBar(); } + + entity.DrawChatBubbles(); } } + } - for (var y = 0; y < Options.MapHeight * 5; y++) + for (var y = 0; y < Options.MapHeight * 5; y++) + { + for (var x = 3; x < 6; x++) { - for (var x = 3; x < 6; x++) + foreach (var entity in RenderingEntities[x, y]) { - foreach (var entity in RenderingEntities[x, y]) + entity.DrawName(null); + if (entity.GetType() != typeof(Event)) { - entity.DrawName(null); - if (entity.GetType() != typeof(Event)) - { - entity.DrawHpBar(); - entity.DrawCastingBar(); - } - - entity.DrawChatBubbles(); + entity.DrawHpBar(); + entity.DrawCastingBar(); } + + entity.DrawChatBubbles(); } } + } - //Draw action msg's - for (var x = gridX - 1; x <= gridX + 1; x++) + //Draw action msg's + for (var x = gridX - 1; x <= gridX + 1; x++) + { + for (var y = gridY - 1; y <= gridY + 1; y++) { - for (var y = gridY - 1; y <= gridY + 1; y++) + if (x < 0 || + x >= Globals.MapGridWidth || + y < 0 || + y >= Globals.MapGridHeight || + Globals.MapGrid[x, y] == Guid.Empty) { - if (x < 0 || - x >= Globals.MapGridWidth || - y < 0 || - y >= Globals.MapGridHeight || - Globals.MapGrid[x, y] == Guid.Empty) - { - continue; - } - - var map = MapInstance.Get(Globals.MapGrid[x, y]); - map?.DrawActionMsgs(); + continue; } - } - foreach (var animInstance in animations) - { - animInstance.EndDraw(); + var map = MapInstance.Get(Globals.MapGrid[x, y]); + map?.DrawActionMsgs(); } } - //Game Rendering - public static void Render(TimeSpan deltaTime, TimeSpan totalTime) + foreach (var animInstance in animations) { - var takingScreenshot = false; - if (Renderer?.ScreenshotRequests.Count > 0) - { - takingScreenshot = Renderer.BeginScreenshot(); - } + animInstance.EndDraw(); + } + } - if (Renderer == default) - { - return; - } + //Game Rendering + public static void Render(TimeSpan deltaTime, TimeSpan totalTime) + { + var takingScreenshot = false; + if (Renderer?.ScreenshotRequests.Count > 0) + { + takingScreenshot = Renderer.BeginScreenshot(); + } - Renderer.Scale = Globals.GameState == GameStates.InGame ? Globals.Database.WorldZoom : 1.0f; + if (Renderer == default) + { + return; + } - if (!Renderer.Begin()) - { - return; - } + Renderer.Scale = Globals.GameState == GameStates.InGame ? Globals.Database.WorldZoom : 1.0f; - if (Renderer.GetScreenWidth() != sOldWidth || - Renderer.GetScreenHeight() != sOldHeight || - Renderer.DisplayModeChanged()) - { - sDarknessTexture = null; - Interface.Interface.DestroyGwen(); - Interface.Interface.InitGwen(); - sOldWidth = Renderer.GetScreenWidth(); - sOldHeight = Renderer.GetScreenHeight(); - } + if (!Renderer.Begin()) + { + return; + } - Renderer.Clear(Color.Black); - DrawCalls = 0; - MapsDrawn = 0; - EntitiesDrawn = 0; - LightsDrawn = 0; + if (Renderer.GetScreenWidth() != sOldWidth || + Renderer.GetScreenHeight() != sOldHeight || + Renderer.DisplayModeChanged()) + { + sDarknessTexture = null; + Interface.Interface.DestroyGwen(); + Interface.Interface.InitGwen(); + sOldWidth = Renderer.GetScreenWidth(); + sOldHeight = Renderer.GetScreenHeight(); + } - UpdateView(); + Renderer.Clear(Color.Black); + DrawCalls = 0; + MapsDrawn = 0; + EntitiesDrawn = 0; + LightsDrawn = 0; - switch (Globals.GameState) - { - case GameStates.Intro: - DrawIntro(); - - break; - case GameStates.Menu: - DrawMenu(); - - break; - case GameStates.Loading: - break; - case GameStates.InGame: - DrawInGame(deltaTime); - - break; - case GameStates.Error: - break; - default: - throw new ArgumentOutOfRangeException(); - } + UpdateView(); + + switch (Globals.GameState) + { + case GameStates.Intro: + DrawIntro(); + + break; + case GameStates.Menu: + DrawMenu(); + + break; + case GameStates.Loading: + break; + case GameStates.InGame: + DrawInGame(deltaTime); + + break; + case GameStates.Error: + break; + default: + throw new ArgumentOutOfRangeException(); + } - Renderer.Scale = Globals.Database.UIScale; + Renderer.Scale = Globals.Database.UIScale; - Interface.Interface.DrawGui(); + Interface.Interface.DrawGui(); + DrawGameTexture( + Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), CurrentView, + new Color((int)Fade.Alpha, 0, 0, 0), null, GameBlendModes.None + ); + + // Draw our mousecursor at the very end, but not when taking screenshots. + if (!takingScreenshot && !string.IsNullOrWhiteSpace(ClientConfiguration.Instance.MouseCursor)) + { + var renderLoc = ConvertToWorldPointNoZoom(Globals.InputManager.GetMousePosition()); DrawGameTexture( - Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), CurrentView, - new Color((int)Fade.Alpha, 0, 0, 0), null, GameBlendModes.None - ); + Globals.ContentManager.GetTexture(Framework.Content.TextureType.Misc, ClientConfiguration.Instance.MouseCursor), renderLoc.X, renderLoc.Y + ); + } - // Draw our mousecursor at the very end, but not when taking screenshots. - if (!takingScreenshot && !string.IsNullOrWhiteSpace(ClientConfiguration.Instance.MouseCursor)) - { - var renderLoc = ConvertToWorldPointNoZoom(Globals.InputManager.GetMousePosition()); - DrawGameTexture( - Globals.ContentManager.GetTexture(Framework.Content.TextureType.Misc, ClientConfiguration.Instance.MouseCursor), renderLoc.X, renderLoc.Y - ); - } + Renderer.End(); - Renderer.End(); + if (takingScreenshot) + { + Renderer.EndScreenshot(); + } + } - if (takingScreenshot) - { - Renderer.EndScreenshot(); - } + private static void DrawMap(Guid mapId, int layer = 0) + { + var map = MapInstance.Get(mapId); + if (map == null) + { + return; } - private static void DrawMap(Guid mapId, int layer = 0) + if (!new FloatRect( + map.GetX(), map.GetY(), Options.TileWidth * Options.MapWidth, Options.TileHeight * Options.MapHeight + ).IntersectsWith(WorldViewport)) { - var map = MapInstance.Get(mapId); - if (map == null) - { - return; - } + return; + } + + map.Draw(layer); + if (layer == 0) + { + MapsDrawn++; + } + } + private static void DrawMapPanorama(Guid mapId) + { + var map = MapInstance.Get(mapId); + if (map != null) + { if (!new FloatRect( map.GetX(), map.GetY(), Options.TileWidth * Options.MapWidth, Options.TileHeight * Options.MapHeight ).IntersectsWith(WorldViewport)) @@ -630,841 +649,820 @@ private static void DrawMap(Guid mapId, int layer = 0) return; } - map.Draw(layer); - if (layer == 0) - { - MapsDrawn++; - } + map.DrawPanorama(); } + } - private static void DrawMapPanorama(Guid mapId) + public static void DrawOverlay() + { + var map = MapInstance.Get(Globals.Me.MapId); + if (map != null) { - var map = MapInstance.Get(mapId); - if (map != null) + float ecTime = Timing.Global.MillisecondsUtc - sOverlayUpdate; + + if (OverlayColor.A != map.AHue || + OverlayColor.R != map.RHue || + OverlayColor.G != map.GHue || + OverlayColor.B != map.BHue) { - if (!new FloatRect( - map.GetX(), map.GetY(), Options.TileWidth * Options.MapWidth, Options.TileHeight * Options.MapHeight - ).IntersectsWith(WorldViewport)) + if (OverlayColor.A < map.AHue) { - return; + if (OverlayColor.A + (int)(255 * ecTime / 2000f) > map.AHue) + { + OverlayColor.A = (byte)map.AHue; + } + else + { + OverlayColor.A += (byte)(255 * ecTime / 2000f); + } } - map.DrawPanorama(); - } - } - - public static void DrawOverlay() - { - var map = MapInstance.Get(Globals.Me.MapId); - if (map != null) - { - float ecTime = Timing.Global.MillisecondsUtc - sOverlayUpdate; - - if (OverlayColor.A != map.AHue || - OverlayColor.R != map.RHue || - OverlayColor.G != map.GHue || - OverlayColor.B != map.BHue) + if (OverlayColor.A > map.AHue) { - if (OverlayColor.A < map.AHue) + if (OverlayColor.A - (int)(255 * ecTime / 2000f) < map.AHue) { - if (OverlayColor.A + (int)(255 * ecTime / 2000f) > map.AHue) - { - OverlayColor.A = (byte)map.AHue; - } - else - { - OverlayColor.A += (byte)(255 * ecTime / 2000f); - } + OverlayColor.A = (byte)map.AHue; } - - if (OverlayColor.A > map.AHue) + else { - if (OverlayColor.A - (int)(255 * ecTime / 2000f) < map.AHue) - { - OverlayColor.A = (byte)map.AHue; - } - else - { - OverlayColor.A -= (byte)(255 * ecTime / 2000f); - } + OverlayColor.A -= (byte)(255 * ecTime / 2000f); } + } - if (OverlayColor.R < map.RHue) + if (OverlayColor.R < map.RHue) + { + if (OverlayColor.R + (int)(255 * ecTime / 2000f) > map.RHue) { - if (OverlayColor.R + (int)(255 * ecTime / 2000f) > map.RHue) - { - OverlayColor.R = (byte)map.RHue; - } - else - { - OverlayColor.R += (byte)(255 * ecTime / 2000f); - } + OverlayColor.R = (byte)map.RHue; } - - if (OverlayColor.R > map.RHue) + else { - if (OverlayColor.R - (int)(255 * ecTime / 2000f) < map.RHue) - { - OverlayColor.R = (byte)map.RHue; - } - else - { - OverlayColor.R -= (byte)(255 * ecTime / 2000f); - } + OverlayColor.R += (byte)(255 * ecTime / 2000f); } + } - if (OverlayColor.G < map.GHue) + if (OverlayColor.R > map.RHue) + { + if (OverlayColor.R - (int)(255 * ecTime / 2000f) < map.RHue) { - if (OverlayColor.G + (int)(255 * ecTime / 2000f) > map.GHue) - { - OverlayColor.G = (byte)map.GHue; - } - else - { - OverlayColor.G += (byte)(255 * ecTime / 2000f); - } + OverlayColor.R = (byte)map.RHue; } - - if (OverlayColor.G > map.GHue) + else { - if (OverlayColor.G - (int)(255 * ecTime / 2000f) < map.GHue) - { - OverlayColor.G = (byte)map.GHue; - } - else - { - OverlayColor.G -= (byte)(255 * ecTime / 2000f); - } + OverlayColor.R -= (byte)(255 * ecTime / 2000f); } + } - if (OverlayColor.B < map.BHue) + if (OverlayColor.G < map.GHue) + { + if (OverlayColor.G + (int)(255 * ecTime / 2000f) > map.GHue) { - if (OverlayColor.B + (int)(255 * ecTime / 2000f) > map.BHue) - { - OverlayColor.B = (byte)map.BHue; - } - else - { - OverlayColor.B += (byte)(255 * ecTime / 2000f); - } + OverlayColor.G = (byte)map.GHue; } - - if (OverlayColor.B > map.BHue) + else { - if (OverlayColor.B - (int)(255 * ecTime / 2000f) < map.BHue) - { - OverlayColor.B = (byte)map.BHue; - } - else - { - OverlayColor.B -= (byte)(255 * ecTime / 2000f); - } + OverlayColor.G += (byte)(255 * ecTime / 2000f); } } - } - DrawGameTexture(Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), CurrentView, OverlayColor, null); - sOverlayUpdate = Timing.Global.MillisecondsUtc; - } + if (OverlayColor.G > map.GHue) + { + if (OverlayColor.G - (int)(255 * ecTime / 2000f) < map.GHue) + { + OverlayColor.G = (byte)map.GHue; + } + else + { + OverlayColor.G -= (byte)(255 * ecTime / 2000f); + } + } - public static FloatRect GetSourceRect(GameTexture gameTexture) - { - return gameTexture == null - ? new FloatRect() - : new FloatRect(0, 0, gameTexture.GetWidth(), gameTexture.GetHeight()); - } + if (OverlayColor.B < map.BHue) + { + if (OverlayColor.B + (int)(255 * ecTime / 2000f) > map.BHue) + { + OverlayColor.B = (byte)map.BHue; + } + else + { + OverlayColor.B += (byte)(255 * ecTime / 2000f); + } + } - public static void DrawFullScreenTexture(GameTexture tex, float alpha = 1f) - { - var bgx = Renderer.GetScreenWidth() / 2 - tex.GetWidth() / 2; - var bgy = Renderer.GetScreenHeight() / 2 - tex.GetHeight() / 2; - var bgw = tex.GetWidth(); - var bgh = tex.GetHeight(); - var diff = 0; - if (bgw < Renderer.GetScreenWidth()) - { - diff = Renderer.GetScreenWidth() - bgw; - bgx -= diff / 2; - bgw += diff; + if (OverlayColor.B > map.BHue) + { + if (OverlayColor.B - (int)(255 * ecTime / 2000f) < map.BHue) + { + OverlayColor.B = (byte)map.BHue; + } + else + { + OverlayColor.B -= (byte)(255 * ecTime / 2000f); + } + } } + } - if (bgh < Renderer.GetScreenHeight()) - { - diff = Renderer.GetScreenHeight() - bgh; - bgy -= diff / 2; - bgh += diff; - } + DrawGameTexture(Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), CurrentView, OverlayColor, null); + sOverlayUpdate = Timing.Global.MillisecondsUtc; + } - DrawGameTexture( - tex, GetSourceRect(tex), - new FloatRect(bgx + Renderer.GetView().X, bgy + Renderer.GetView().Y, bgw, bgh), - new Color((int)(alpha * 255f), 255, 255, 255) - ); - } + public static FloatRect GetSourceRect(GameTexture gameTexture) + { + return gameTexture == null + ? new FloatRect() + : new FloatRect(0, 0, gameTexture.GetWidth(), gameTexture.GetHeight()); + } - public static void DrawFullScreenTextureCentered(GameTexture tex, float alpha = 1f) + public static void DrawFullScreenTexture(GameTexture tex, float alpha = 1f) + { + var bgx = Renderer.GetScreenWidth() / 2 - tex.GetWidth() / 2; + var bgy = Renderer.GetScreenHeight() / 2 - tex.GetHeight() / 2; + var bgw = tex.GetWidth(); + var bgh = tex.GetHeight(); + var diff = 0; + if (bgw < Renderer.GetScreenWidth()) { - var bgx = Renderer.GetScreenWidth() / 2 - tex.GetWidth() / 2; - var bgy = Renderer.GetScreenHeight() / 2 - tex.GetHeight() / 2; - var bgw = tex.GetWidth(); - var bgh = tex.GetHeight(); - - DrawGameTexture( - tex, GetSourceRect(tex), - new FloatRect(bgx + Renderer.GetView().X, bgy + Renderer.GetView().Y, bgw, bgh), - new Color((int)(alpha * 255f), 255, 255, 255) - ); + diff = Renderer.GetScreenWidth() - bgw; + bgx -= diff / 2; + bgw += diff; } - public static void DrawFullScreenTextureStretched(GameTexture tex) + if (bgh < Renderer.GetScreenHeight()) { - DrawGameTexture( - tex, GetSourceRect(tex), - new FloatRect( - Renderer.GetView().X, Renderer.GetView().Y, Renderer.GetScreenWidth(), Renderer.GetScreenHeight() - ), Color.White - ); + diff = Renderer.GetScreenHeight() - bgh; + bgy -= diff / 2; + bgh += diff; } - public static void DrawFullScreenTextureFitWidth(GameTexture tex) + DrawGameTexture( + tex, GetSourceRect(tex), + new FloatRect(bgx + Renderer.GetView().X, bgy + Renderer.GetView().Y, bgw, bgh), + new Color((int)(alpha * 255f), 255, 255, 255) + ); + } + + public static void DrawFullScreenTextureCentered(GameTexture tex, float alpha = 1f) + { + var bgx = Renderer.GetScreenWidth() / 2 - tex.GetWidth() / 2; + var bgy = Renderer.GetScreenHeight() / 2 - tex.GetHeight() / 2; + var bgw = tex.GetWidth(); + var bgh = tex.GetHeight(); + + DrawGameTexture( + tex, GetSourceRect(tex), + new FloatRect(bgx + Renderer.GetView().X, bgy + Renderer.GetView().Y, bgw, bgh), + new Color((int)(alpha * 255f), 255, 255, 255) + ); + } + + public static void DrawFullScreenTextureStretched(GameTexture tex) + { + DrawGameTexture( + tex, GetSourceRect(tex), + new FloatRect( + Renderer.GetView().X, Renderer.GetView().Y, Renderer.GetScreenWidth(), Renderer.GetScreenHeight() + ), Color.White + ); + } + + public static void DrawFullScreenTextureFitWidth(GameTexture tex) + { + var scale = Renderer.GetScreenWidth() / (float)tex.GetWidth(); + var scaledHeight = tex.GetHeight() * scale; + var offsetY = (Renderer.GetScreenHeight() - tex.GetHeight()) / 2f; + DrawGameTexture( + tex, GetSourceRect(tex), + new FloatRect( + Renderer.GetView().X, Renderer.GetView().Y + offsetY, Renderer.GetScreenWidth(), scaledHeight + ), Color.White + ); + } + + public static void DrawFullScreenTextureFitHeight(GameTexture tex) + { + var scale = Renderer.GetScreenHeight() / (float)tex.GetHeight(); + var scaledWidth = tex.GetWidth() * scale; + var offsetX = (Renderer.GetScreenWidth() - scaledWidth) / 2f; + DrawGameTexture( + tex, GetSourceRect(tex), + new FloatRect( + Renderer.GetView().X + offsetX, Renderer.GetView().Y, scaledWidth, Renderer.GetScreenHeight() + ), Color.White + ); + } + + public static void DrawFullScreenTextureFitMinimum(GameTexture tex) + { + if (Renderer.GetScreenWidth() > Renderer.GetScreenHeight()) { - var scale = Renderer.GetScreenWidth() / (float)tex.GetWidth(); - var scaledHeight = tex.GetHeight() * scale; - var offsetY = (Renderer.GetScreenHeight() - tex.GetHeight()) / 2f; - DrawGameTexture( - tex, GetSourceRect(tex), - new FloatRect( - Renderer.GetView().X, Renderer.GetView().Y + offsetY, Renderer.GetScreenWidth(), scaledHeight - ), Color.White - ); + DrawFullScreenTextureFitHeight(tex); } - - public static void DrawFullScreenTextureFitHeight(GameTexture tex) + else { - var scale = Renderer.GetScreenHeight() / (float)tex.GetHeight(); - var scaledWidth = tex.GetWidth() * scale; - var offsetX = (Renderer.GetScreenWidth() - scaledWidth) / 2f; - DrawGameTexture( - tex, GetSourceRect(tex), - new FloatRect( - Renderer.GetView().X + offsetX, Renderer.GetView().Y, scaledWidth, Renderer.GetScreenHeight() - ), Color.White - ); + DrawFullScreenTextureFitWidth(tex); } + } - public static void DrawFullScreenTextureFitMinimum(GameTexture tex) + public static void DrawFullScreenTextureFitMaximum(GameTexture tex) + { + if (Renderer.GetScreenWidth() < Renderer.GetScreenHeight()) { - if (Renderer.GetScreenWidth() > Renderer.GetScreenHeight()) - { - DrawFullScreenTextureFitHeight(tex); - } - else - { - DrawFullScreenTextureFitWidth(tex); - } + DrawFullScreenTextureFitHeight(tex); + } + else + { + DrawFullScreenTextureFitWidth(tex); } + } - public static void DrawFullScreenTextureFitMaximum(GameTexture tex) + private static void UpdateView() + { + var scale = Renderer.Scale; + + if (Globals.GameState != GameStates.InGame || !MapInstance.TryGet(Globals.Me?.MapId ?? Guid.Empty, out var map)) { - if (Renderer.GetScreenWidth() < Renderer.GetScreenHeight()) - { - DrawFullScreenTextureFitHeight(tex); - } - else - { - DrawFullScreenTextureFitWidth(tex); - } + var sw = Renderer.GetScreenWidth(); + var sh = Renderer.GetScreenHeight(); + var sx = 0;//sw - (sw / scale); + var sy = 0;//sh - (sh / scale); + CurrentView = new FloatRect(sx, sy, sw / scale, sh / scale); + return; } - private static void UpdateView() + var mapWidth = Options.MapWidth * Options.TileWidth; + var mapHeight = Options.MapHeight * Options.TileHeight; + + var en = Globals.Me; + float x = mapWidth; + float y = mapHeight; + float x1 = mapWidth * 2; + float y1 = mapHeight * 2; + + if (map.CameraHolds[(int)Direction.Left]) { - var scale = Renderer.Scale; + x -= mapWidth; + } - if (Globals.GameState != GameStates.InGame || !MapInstance.TryGet(Globals.Me?.MapId ?? Guid.Empty, out var map)) - { - var sw = Renderer.GetScreenWidth(); - var sh = Renderer.GetScreenHeight(); - var sx = 0;//sw - (sw / scale); - var sy = 0;//sh - (sh / scale); - CurrentView = new FloatRect(sx, sy, sw / scale, sh / scale); - return; - } + if (map.CameraHolds[(int)Direction.Up]) + { + y -= mapHeight; + } - var mapWidth = Options.MapWidth * Options.TileWidth; - var mapHeight = Options.MapHeight * Options.TileHeight; + if (map.CameraHolds[(int)Direction.Right]) + { + x1 -= mapWidth; + } - var en = Globals.Me; - float x = mapWidth; - float y = mapHeight; - float x1 = mapWidth * 2; - float y1 = mapHeight * 2; + if (map.CameraHolds[(int)Direction.Down]) + { + y1 -= mapHeight; + } - if (map.CameraHolds[(int)Direction.Left]) + x = map.GetX() - x; + y = map.GetY() - y; + x1 = map.GetX() + x1; + y1 = map.GetY() + y1; + + var w = x1 - x; + var h = y1 - y; + var restrictView = new FloatRect( + x, + y, + w, + h + ); + var newView = new FloatRect( + (int)Math.Ceiling(en.Center.X - Renderer.ScreenWidth / scale / 2f), + (int)Math.Ceiling(en.Center.Y - Renderer.ScreenHeight / scale / 2f), + Renderer.ScreenWidth / scale, + Renderer.ScreenHeight / scale + ); + + if (restrictView.Width >= newView.Width) + { + if (newView.Left < restrictView.Left) { - x -= mapWidth; + newView.X = restrictView.Left; } - if (map.CameraHolds[(int)Direction.Up]) + if (newView.Right > restrictView.Right) { - y -= mapHeight; + newView.X = restrictView.Right - newView.Width; } + } - if (map.CameraHolds[(int)Direction.Right]) + if (restrictView.Height >= newView.Height) + { + if (newView.Top < restrictView.Top) { - x1 -= mapWidth; + newView.Y = restrictView.Top; } - if (map.CameraHolds[(int)Direction.Down]) + if (newView.Bottom > restrictView.Bottom) { - y1 -= mapHeight; + newView.Y = restrictView.Bottom - newView.Height; } + } - x = map.GetX() - x; - y = map.GetY() - y; - x1 = map.GetX() + x1; - y1 = map.GetY() + y1; - - var w = x1 - x; - var h = y1 - y; - var restrictView = new FloatRect( - x, - y, - w, - h - ); - var newView = new FloatRect( - (int)Math.Ceiling(en.Center.X - Renderer.ScreenWidth / scale / 2f), - (int)Math.Ceiling(en.Center.Y - Renderer.ScreenHeight / scale / 2f), - Renderer.ScreenWidth / scale, - Renderer.ScreenHeight / scale - ); - - if (restrictView.Width >= newView.Width) - { - if (newView.Left < restrictView.Left) - { - newView.X = restrictView.Left; - } + CurrentView = new FloatRect( + newView.X, + newView.Y, + newView.Width * scale, + newView.Height * scale + ); + } - if (newView.Right > restrictView.Right) - { - newView.X = restrictView.Right - newView.Width; - } - } + //Lighting + private static void ClearDarknessTexture() + { + // If we're not allowed to draw lighting, exit out. + if (!Globals.Database.EnableLighting) + { + return; + } - if (restrictView.Height >= newView.Height) - { - if (newView.Top < restrictView.Top) - { - newView.Y = restrictView.Top; - } + if (sDarknessTexture == null) + { + sDarknessTexture = Renderer.CreateRenderTexture(Renderer.GetScreenWidth(), Renderer.GetScreenHeight()); + } - if (newView.Bottom > restrictView.Bottom) - { - newView.Y = restrictView.Bottom - newView.Height; - } - } + sDarknessTexture.Clear(Color.Black); + } - CurrentView = new FloatRect( - newView.X, - newView.Y, - newView.Width * scale, - newView.Height * scale - ); + private static void GenerateLightMap() + { + // If we're not allowed to draw lighting, exit out. + if (!Globals.Database.EnableLighting) + { + return; } - //Lighting - private static void ClearDarknessTexture() + var map = MapInstance.Get(Globals.Me.MapId); + if (map == null) { - // If we're not allowed to draw lighting, exit out. - if (!Globals.Database.EnableLighting) - { - return; - } - - if (sDarknessTexture == null) - { - sDarknessTexture = Renderer.CreateRenderTexture(Renderer.GetScreenWidth(), Renderer.GetScreenHeight()); - } + return; + } - sDarknessTexture.Clear(Color.Black); + if (sDarknessTexture == null) + { + return; } - private static void GenerateLightMap() + var destRect = new FloatRect(new Pointf(), sDarknessTexture.Dimensions / Globals.Database.WorldZoom); + if (map.IsIndoors) { - // If we're not allowed to draw lighting, exit out. - if (!Globals.Database.EnableLighting) - { - return; - } + DrawGameTexture( + Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), + destRect, + new Color((byte)BrightnessLevel, 255, 255, 255), sDarknessTexture, GameBlendModes.Add + ); + } + else + { + DrawGameTexture( + Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), + destRect, + new Color(255, 255, 255, 255), sDarknessTexture, GameBlendModes.Add + ); - var map = MapInstance.Get(Globals.Me.MapId); - if (map == null) - { - return; - } + DrawGameTexture( + Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), + destRect, + new Color( + (int)Time.GetTintColor().A, (int)Time.GetTintColor().R, (int)Time.GetTintColor().G, + (int)Time.GetTintColor().B + ), sDarknessTexture, GameBlendModes.None + ); + } - if (sDarknessTexture == null) - { - return; - } + AddLight( + (int)Math.Ceiling(Globals.Me.Center.X), (int)Math.Ceiling(Globals.Me.Center.Y), + (int)sPlayerLightSize, (byte)sPlayerLightIntensity, sPlayerLightExpand, + Color.FromArgb( + (int)PlayerLightColor.A, (int)PlayerLightColor.R, (int)PlayerLightColor.G, + (int)PlayerLightColor.B + ) + ); + + DrawLights(); + sDarknessTexture.End(); + } - var destRect = new FloatRect(new Pointf(), sDarknessTexture.Dimensions / Globals.Database.WorldZoom); - if (map.IsIndoors) - { - DrawGameTexture( - Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), - destRect, - new Color((byte)BrightnessLevel, 255, 255, 255), sDarknessTexture, GameBlendModes.Add - ); - } - else - { - DrawGameTexture( - Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), - destRect, - new Color(255, 255, 255, 255), sDarknessTexture, GameBlendModes.Add - ); - - DrawGameTexture( - Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), - destRect, - new Color( - (int)Time.GetTintColor().A, (int)Time.GetTintColor().R, (int)Time.GetTintColor().G, - (int)Time.GetTintColor().B - ), sDarknessTexture, GameBlendModes.None - ); - } + public static void DrawDarkness() + { + // If we're not allowed to draw lighting, exit out. + if (!Globals.Database.EnableLighting) + { + return; + } - AddLight( - (int)Math.Ceiling(Globals.Me.Center.X), (int)Math.Ceiling(Globals.Me.Center.Y), - (int)sPlayerLightSize, (byte)sPlayerLightIntensity, sPlayerLightExpand, - Color.FromArgb( - (int)PlayerLightColor.A, (int)PlayerLightColor.R, (int)PlayerLightColor.G, - (int)PlayerLightColor.B - ) + var radialShader = Globals.ContentManager.GetShader("radialgradient"); + if (radialShader != null) + { + DrawGameTexture( + sDarknessTexture, + sDarknessTexture.Bounds, + WorldViewport, + Color.White, + blendMode: GameBlendModes.Multiply ); - - DrawLights(); - sDarknessTexture.End(); } + } - public static void DrawDarkness() + public static void AddLight(int x, int y, int size, byte intensity, float expand, Color color) + { + // If we're not allowed to draw lighting, exit out. + if (!Globals.Database.EnableLighting) { - // If we're not allowed to draw lighting, exit out. - if (!Globals.Database.EnableLighting) - { - return; - } - - var radialShader = Globals.ContentManager.GetShader("radialgradient"); - if (radialShader != null) - { - DrawGameTexture( - sDarknessTexture, - sDarknessTexture.Bounds, - WorldViewport, - Color.White, - blendMode: GameBlendModes.Multiply - ); - } + return; } - public static void AddLight(int x, int y, int size, byte intensity, float expand, Color color) + if (size == 0) { - // If we're not allowed to draw lighting, exit out. - if (!Globals.Database.EnableLighting) - { - return; - } + return; + } - if (size == 0) - { - return; - } + sLightQueue.Add(new LightBase(0, 0, x, y, intensity, size, expand, color)); + LightsDrawn++; + } - sLightQueue.Add(new LightBase(0, 0, x, y, intensity, size, expand, color)); - LightsDrawn++; + private static void DrawLights() + { + // If we're not allowed to draw lighting, exit out. + if (!Globals.Database.EnableLighting) + { + return; } - private static void DrawLights() + var radialShader = Globals.ContentManager.GetShader("radialgradient"); + if (radialShader != null) { - // If we're not allowed to draw lighting, exit out. - if (!Globals.Database.EnableLighting) + foreach (var light in sLightQueue.GroupBy(c => c.GetHashCode())) { - return; - } - - var radialShader = Globals.ContentManager.GetShader("radialgradient"); - if (radialShader != null) - { - foreach (var light in sLightQueue.GroupBy(c => c.GetHashCode())) + foreach (var l in light) { - foreach (var l in light) - { - var x = l.OffsetX - ((int)CurrentView.Left + l.Size); - var y = l.OffsetY - ((int)CurrentView.Top + l.Size); + var x = l.OffsetX - ((int)CurrentView.Left + l.Size); + var y = l.OffsetY - ((int)CurrentView.Top + l.Size); - radialShader.SetColor("LightColor", new Color(l.Intensity, l.Color.R, l.Color.G, l.Color.B)); - radialShader.SetFloat("Expand", l.Expand / 100f); + radialShader.SetColor("LightColor", new Color(l.Intensity, l.Color.R, l.Color.G, l.Color.B)); + radialShader.SetFloat("Expand", l.Expand / 100f); - DrawGameTexture( - Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), - new FloatRect(x, y, l.Size * 2, l.Size * 2), new Color(255, 255, 255, 255), sDarknessTexture, GameBlendModes.Add, radialShader, 0, false - ); + DrawGameTexture( + Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), + new FloatRect(x, y, l.Size * 2, l.Size * 2), new Color(255, 255, 255, 255), sDarknessTexture, GameBlendModes.Add, radialShader, 0, false + ); - } } - - sLightQueue.Clear(); } + + sLightQueue.Clear(); } + } - public static void UpdatePlayerLight() + public static void UpdatePlayerLight() + { + // If we're not allowed to draw lighting, exit out. + if (!Globals.Database.EnableLighting) { - // If we're not allowed to draw lighting, exit out. - if (!Globals.Database.EnableLighting) + return; + } + + //Draw Light Around Player + var map = MapInstance.Get(Globals.Me.MapId); + if (map != null) + { + float ecTime = Timing.Global.MillisecondsUtc - sLightUpdate; + var valChange = 255 * ecTime / 2000f; + var brightnessTarget = (byte)(map.Brightness / 100f * 255); + if (BrightnessLevel < brightnessTarget) { - return; + if (BrightnessLevel + valChange > brightnessTarget) + { + BrightnessLevel = brightnessTarget; + } + else + { + BrightnessLevel += valChange; + } } - //Draw Light Around Player - var map = MapInstance.Get(Globals.Me.MapId); - if (map != null) + if (BrightnessLevel > brightnessTarget) { - float ecTime = Timing.Global.MillisecondsUtc - sLightUpdate; - var valChange = 255 * ecTime / 2000f; - var brightnessTarget = (byte)(map.Brightness / 100f * 255); - if (BrightnessLevel < brightnessTarget) + if (BrightnessLevel - valChange < brightnessTarget) { - if (BrightnessLevel + valChange > brightnessTarget) - { - BrightnessLevel = brightnessTarget; - } - else - { - BrightnessLevel += valChange; - } + BrightnessLevel = brightnessTarget; } + else + { + BrightnessLevel -= valChange; + } + } - if (BrightnessLevel > brightnessTarget) + if (PlayerLightColor.R != map.PlayerLightColor.R || + PlayerLightColor.G != map.PlayerLightColor.G || + PlayerLightColor.B != map.PlayerLightColor.B) + { + if (PlayerLightColor.R < map.PlayerLightColor.R) { - if (BrightnessLevel - valChange < brightnessTarget) + if (PlayerLightColor.R + valChange > map.PlayerLightColor.R) { - BrightnessLevel = brightnessTarget; + PlayerLightColor.R = map.PlayerLightColor.R; } else { - BrightnessLevel -= valChange; + PlayerLightColor.R += valChange; } } - if (PlayerLightColor.R != map.PlayerLightColor.R || - PlayerLightColor.G != map.PlayerLightColor.G || - PlayerLightColor.B != map.PlayerLightColor.B) + if (PlayerLightColor.R > map.PlayerLightColor.R) { - if (PlayerLightColor.R < map.PlayerLightColor.R) + if (PlayerLightColor.R - valChange < map.PlayerLightColor.R) { - if (PlayerLightColor.R + valChange > map.PlayerLightColor.R) - { - PlayerLightColor.R = map.PlayerLightColor.R; - } - else - { - PlayerLightColor.R += valChange; - } + PlayerLightColor.R = map.PlayerLightColor.R; } - - if (PlayerLightColor.R > map.PlayerLightColor.R) + else { - if (PlayerLightColor.R - valChange < map.PlayerLightColor.R) - { - PlayerLightColor.R = map.PlayerLightColor.R; - } - else - { - PlayerLightColor.R -= valChange; - } - } - - if (PlayerLightColor.G < map.PlayerLightColor.G) - { - if (PlayerLightColor.G + valChange > map.PlayerLightColor.G) - { - PlayerLightColor.G = map.PlayerLightColor.G; - } - else - { - PlayerLightColor.G += valChange; - } + PlayerLightColor.R -= valChange; } + } - if (PlayerLightColor.G > map.PlayerLightColor.G) + if (PlayerLightColor.G < map.PlayerLightColor.G) + { + if (PlayerLightColor.G + valChange > map.PlayerLightColor.G) { - if (PlayerLightColor.G - valChange < map.PlayerLightColor.G) - { - PlayerLightColor.G = map.PlayerLightColor.G; - } - else - { - PlayerLightColor.G -= valChange; - } + PlayerLightColor.G = map.PlayerLightColor.G; } - - if (PlayerLightColor.B < map.PlayerLightColor.B) + else { - if (PlayerLightColor.B + valChange > map.PlayerLightColor.B) - { - PlayerLightColor.B = map.PlayerLightColor.B; - } - else - { - PlayerLightColor.B += valChange; - } - } - - if (PlayerLightColor.B > map.PlayerLightColor.B) - { - if (PlayerLightColor.B - valChange < map.PlayerLightColor.B) - { - PlayerLightColor.B = map.PlayerLightColor.B; - } - else - { - PlayerLightColor.B -= valChange; - } + PlayerLightColor.G += valChange; } } - if (sPlayerLightSize != map.PlayerLightSize) + if (PlayerLightColor.G > map.PlayerLightColor.G) { - if (sPlayerLightSize < map.PlayerLightSize) + if (PlayerLightColor.G - valChange < map.PlayerLightColor.G) { - if (sPlayerLightSize + 500 * ecTime / 2000f > map.PlayerLightSize) - { - sPlayerLightSize = map.PlayerLightSize; - } - else - { - sPlayerLightSize += 500 * ecTime / 2000f; - } + PlayerLightColor.G = map.PlayerLightColor.G; } - - if (sPlayerLightSize > map.PlayerLightSize) + else { - if (sPlayerLightSize - 500 * ecTime / 2000f < map.PlayerLightSize) - { - sPlayerLightSize = map.PlayerLightSize; - } - else - { - sPlayerLightSize -= 500 * ecTime / 2000f; - } + PlayerLightColor.G -= valChange; } } - if (sPlayerLightIntensity < map.PlayerLightIntensity) + if (PlayerLightColor.B < map.PlayerLightColor.B) { - if (sPlayerLightIntensity + valChange > map.PlayerLightIntensity) + if (PlayerLightColor.B + valChange > map.PlayerLightColor.B) { - sPlayerLightIntensity = map.PlayerLightIntensity; + PlayerLightColor.B = map.PlayerLightColor.B; } else { - sPlayerLightIntensity += valChange; + PlayerLightColor.B += valChange; } } - if (sPlayerLightIntensity > map.AHue) + if (PlayerLightColor.B > map.PlayerLightColor.B) { - if (sPlayerLightIntensity - valChange < map.PlayerLightIntensity) + if (PlayerLightColor.B - valChange < map.PlayerLightColor.B) { - sPlayerLightIntensity = map.PlayerLightIntensity; + PlayerLightColor.B = map.PlayerLightColor.B; } else { - sPlayerLightIntensity -= valChange; + PlayerLightColor.B -= valChange; } } + } - if (sPlayerLightExpand < map.PlayerLightExpand) + if (sPlayerLightSize != map.PlayerLightSize) + { + if (sPlayerLightSize < map.PlayerLightSize) { - if (sPlayerLightExpand + 100f * ecTime / 2000f > map.PlayerLightExpand) + if (sPlayerLightSize + 500 * ecTime / 2000f > map.PlayerLightSize) { - sPlayerLightExpand = map.PlayerLightExpand; + sPlayerLightSize = map.PlayerLightSize; } else { - sPlayerLightExpand += 100f * ecTime / 2000f; + sPlayerLightSize += 500 * ecTime / 2000f; } } - if (sPlayerLightExpand > map.PlayerLightExpand) + if (sPlayerLightSize > map.PlayerLightSize) { - if (sPlayerLightExpand - 100f * ecTime / 2000f < map.PlayerLightExpand) + if (sPlayerLightSize - 500 * ecTime / 2000f < map.PlayerLightSize) { - sPlayerLightExpand = map.PlayerLightExpand; + sPlayerLightSize = map.PlayerLightSize; } else { - sPlayerLightExpand -= 100f * ecTime / 2000f; + sPlayerLightSize -= 500 * ecTime / 2000f; } } - - // Cap instensity between 0 and 255 so as not to overflow (as it is an alpha value) - sPlayerLightIntensity = (float)MathHelper.Clamp(sPlayerLightIntensity, 0f, 255f); - sLightUpdate = Timing.Global.MillisecondsUtc; } - } - //Helper Functions - /// - /// Convert a position on the screen to a position on the actual map for rendering. - /// - /// The point to convert. - /// The converted point. - public static Pointf ConvertToWorldPoint(Pointf windowPoint) - { - return new Pointf( - (int)Math.Floor(windowPoint.X / Globals.Database.WorldZoom + CurrentView.Left), - (int)Math.Floor(windowPoint.Y / Globals.Database.WorldZoom + CurrentView.Top) - ); - } + if (sPlayerLightIntensity < map.PlayerLightIntensity) + { + if (sPlayerLightIntensity + valChange > map.PlayerLightIntensity) + { + sPlayerLightIntensity = map.PlayerLightIntensity; + } + else + { + sPlayerLightIntensity += valChange; + } + } - /// - /// Converts a point in the window to its place in the world view without respecting zoom - /// - /// The point to convert. - /// The converted point. - public static Pointf ConvertToWorldPointNoZoom(Pointf windowPoint) - { - return new Pointf((int)Math.Floor(windowPoint.X + CurrentView.Left), (int)Math.Floor(windowPoint.Y + CurrentView.Top)); - } - - //Rendering Functions - - /// - /// Renders a specified texture onto a RenderTexture or the GameScreen (if renderTarget is passed as null) at the - /// coordinates given using a specified blending mode. - /// - /// The texture to draw - /// X coordinate on the render target to draw to - /// Y coordinate on the render target to draw to - /// Where to draw to. If null it this will draw to the game screen. - /// Which blend mode to use when rendering - public static void DrawGameTexture( - GameTexture tex, - float x, - float y, - GameRenderTexture renderTarget = null, - GameBlendModes blendMode = GameBlendModes.None, - GameShader shader = null, - float rotationDegrees = 0.0f, - bool drawImmediate = false - ) - { - var destRectangle = new FloatRect(x, y, tex.GetWidth(), tex.GetHeight()); - var srcRectangle = new FloatRect(0, 0, tex.GetWidth(), tex.GetHeight()); - DrawGameTexture( - tex, srcRectangle, destRectangle, Color.White, renderTarget, blendMode, shader, rotationDegrees, - drawImmediate - ); - } + if (sPlayerLightIntensity > map.AHue) + { + if (sPlayerLightIntensity - valChange < map.PlayerLightIntensity) + { + sPlayerLightIntensity = map.PlayerLightIntensity; + } + else + { + sPlayerLightIntensity -= valChange; + } + } - /// - /// Renders a specified texture onto a RenderTexture or the GameScreen (if renderTarget is passed as null) at the - /// coordinates given using a specified blending mode. - /// - /// The texture to draw - /// X coordinate on the render target to draw to - /// Y coordinate on the render target to draw to - /// Color mask to draw with. Default is Color.White - /// Where to draw to. If null it this will draw to the game screen. - /// Which blend mode to use when rendering - public static void DrawGameTexture( - GameTexture tex, - float x, - float y, - Color renderColor, - GameRenderTexture renderTarget = null, - GameBlendModes blendMode = GameBlendModes.None, - GameShader shader = null, - float rotationDegrees = 0.0f, - bool drawImmediate = false - ) - { - var destRectangle = new FloatRect(x, y, tex.GetWidth(), tex.GetHeight()); - var srcRectangle = new FloatRect(0, 0, tex.GetWidth(), tex.GetHeight()); - DrawGameTexture( - tex, srcRectangle, destRectangle, renderColor, renderTarget, blendMode, shader, rotationDegrees, - drawImmediate - ); - } + if (sPlayerLightExpand < map.PlayerLightExpand) + { + if (sPlayerLightExpand + 100f * ecTime / 2000f > map.PlayerLightExpand) + { + sPlayerLightExpand = map.PlayerLightExpand; + } + else + { + sPlayerLightExpand += 100f * ecTime / 2000f; + } + } - /// - /// Renders a specified texture onto a RenderTexture or the GameScreen (if renderTarget is passed as null) at the - /// coordinates given using a specified blending mode. - /// - /// The texture to draw - /// X coordinate on the renderTarget to draw to. - /// Y coordinate on the renderTarget to draw to. - /// X coordinate on the source texture to grab from. - /// Y coordinate on the source texture to grab from. - /// Width of the texture part we are rendering. - /// Height of the texture part we are rendering. - /// >Where to draw to. If null it this will draw to the game screen. - /// Which blend mode to use when rendering - public static void DrawGameTexture( - GameTexture tex, - float dx, - float dy, - float sx, - float sy, - float w, - float h, - GameRenderTexture renderTarget = null, - GameBlendModes blendMode = GameBlendModes.None, - GameShader shader = null, - float rotationDegrees = 0.0f, - bool drawImmediate = false - ) - { - if (tex == null) + if (sPlayerLightExpand > map.PlayerLightExpand) { - return; + if (sPlayerLightExpand - 100f * ecTime / 2000f < map.PlayerLightExpand) + { + sPlayerLightExpand = map.PlayerLightExpand; + } + else + { + sPlayerLightExpand -= 100f * ecTime / 2000f; + } } - Renderer.DrawTexture( - tex, sx, sy, w, h, dx, dy, w, h, Color.White, renderTarget, blendMode, shader, rotationDegrees, false, - drawImmediate - ); + // Cap instensity between 0 and 255 so as not to overflow (as it is an alpha value) + sPlayerLightIntensity = (float)MathHelper.Clamp(sPlayerLightIntensity, 0f, 255f); + sLightUpdate = Timing.Global.MillisecondsUtc; } + } + + //Helper Functions + /// + /// Convert a position on the screen to a position on the actual map for rendering. + /// + /// The point to convert. + /// The converted point. + public static Pointf ConvertToWorldPoint(Pointf windowPoint) + { + return new Pointf( + (int)Math.Floor(windowPoint.X / Globals.Database.WorldZoom + CurrentView.Left), + (int)Math.Floor(windowPoint.Y / Globals.Database.WorldZoom + CurrentView.Top) + ); + } + + /// + /// Converts a point in the window to its place in the world view without respecting zoom + /// + /// The point to convert. + /// The converted point. + public static Pointf ConvertToWorldPointNoZoom(Pointf windowPoint) + { + return new Pointf((int)Math.Floor(windowPoint.X + CurrentView.Left), (int)Math.Floor(windowPoint.Y + CurrentView.Top)); + } + + //Rendering Functions + + /// + /// Renders a specified texture onto a RenderTexture or the GameScreen (if renderTarget is passed as null) at the + /// coordinates given using a specified blending mode. + /// + /// The texture to draw + /// X coordinate on the render target to draw to + /// Y coordinate on the render target to draw to + /// Where to draw to. If null it this will draw to the game screen. + /// Which blend mode to use when rendering + public static void DrawGameTexture( + GameTexture tex, + float x, + float y, + GameRenderTexture renderTarget = null, + GameBlendModes blendMode = GameBlendModes.None, + GameShader shader = null, + float rotationDegrees = 0.0f, + bool drawImmediate = false + ) + { + var destRectangle = new FloatRect(x, y, tex.GetWidth(), tex.GetHeight()); + var srcRectangle = new FloatRect(0, 0, tex.GetWidth(), tex.GetHeight()); + DrawGameTexture( + tex, srcRectangle, destRectangle, Color.White, renderTarget, blendMode, shader, rotationDegrees, + drawImmediate + ); + } - public static void DrawGameTexture( - GameTexture tex, - FloatRect srcRectangle, - FloatRect targetRect, - Color renderColor, - GameRenderTexture renderTarget = null, - GameBlendModes blendMode = GameBlendModes.None, - GameShader shader = null, - float rotationDegrees = 0.0f, - bool drawImmediate = false - ) + /// + /// Renders a specified texture onto a RenderTexture or the GameScreen (if renderTarget is passed as null) at the + /// coordinates given using a specified blending mode. + /// + /// The texture to draw + /// X coordinate on the render target to draw to + /// Y coordinate on the render target to draw to + /// Color mask to draw with. Default is Color.White + /// Where to draw to. If null it this will draw to the game screen. + /// Which blend mode to use when rendering + public static void DrawGameTexture( + GameTexture tex, + float x, + float y, + Color renderColor, + GameRenderTexture renderTarget = null, + GameBlendModes blendMode = GameBlendModes.None, + GameShader shader = null, + float rotationDegrees = 0.0f, + bool drawImmediate = false + ) + { + var destRectangle = new FloatRect(x, y, tex.GetWidth(), tex.GetHeight()); + var srcRectangle = new FloatRect(0, 0, tex.GetWidth(), tex.GetHeight()); + DrawGameTexture( + tex, srcRectangle, destRectangle, renderColor, renderTarget, blendMode, shader, rotationDegrees, + drawImmediate + ); + } + + /// + /// Renders a specified texture onto a RenderTexture or the GameScreen (if renderTarget is passed as null) at the + /// coordinates given using a specified blending mode. + /// + /// The texture to draw + /// X coordinate on the renderTarget to draw to. + /// Y coordinate on the renderTarget to draw to. + /// X coordinate on the source texture to grab from. + /// Y coordinate on the source texture to grab from. + /// Width of the texture part we are rendering. + /// Height of the texture part we are rendering. + /// >Where to draw to. If null it this will draw to the game screen. + /// Which blend mode to use when rendering + public static void DrawGameTexture( + GameTexture tex, + float dx, + float dy, + float sx, + float sy, + float w, + float h, + GameRenderTexture renderTarget = null, + GameBlendModes blendMode = GameBlendModes.None, + GameShader shader = null, + float rotationDegrees = 0.0f, + bool drawImmediate = false + ) + { + if (tex == null) { - if (tex == null) - { - return; - } + return; + } - Renderer.DrawTexture( - tex, srcRectangle.X, srcRectangle.Y, srcRectangle.Width, srcRectangle.Height, targetRect.X, - targetRect.Y, targetRect.Width, targetRect.Height, - Color.FromArgb(renderColor.A, renderColor.R, renderColor.G, renderColor.B), renderTarget, blendMode, - shader, rotationDegrees, false, drawImmediate - ); + Renderer.DrawTexture( + tex, sx, sy, w, h, dx, dy, w, h, Color.White, renderTarget, blendMode, shader, rotationDegrees, false, + drawImmediate + ); + } + + public static void DrawGameTexture( + GameTexture tex, + FloatRect srcRectangle, + FloatRect targetRect, + Color renderColor, + GameRenderTexture renderTarget = null, + GameBlendModes blendMode = GameBlendModes.None, + GameShader shader = null, + float rotationDegrees = 0.0f, + bool drawImmediate = false + ) + { + if (tex == null) + { + return; } + Renderer.DrawTexture( + tex, srcRectangle.X, srcRectangle.Y, srcRectangle.Width, srcRectangle.Height, targetRect.X, + targetRect.Y, targetRect.Width, targetRect.Height, + Color.FromArgb(renderColor.A, renderColor.R, renderColor.G, renderColor.B), renderTarget, blendMode, + shader, rotationDegrees, false, drawImmediate + ); } } diff --git a/Intersect.Client/Core/IClientContext.cs b/Intersect.Client/Core/IClientContext.cs index 507ac8764f..b7f9bf5f53 100644 --- a/Intersect.Client/Core/IClientContext.cs +++ b/Intersect.Client/Core/IClientContext.cs @@ -1,15 +1,14 @@ using Intersect.Core; -namespace Intersect.Client.Core +namespace Intersect.Client.Core; + +/// +/// Declares the API surface of client contexts. +/// +internal interface IClientContext : IApplicationContext { /// - /// Declares the API surface of client contexts. + /// The platform-specific runner that initializes the actual user-visible client. /// - internal interface IClientContext : IApplicationContext - { - /// - /// The platform-specific runner that initializes the actual user-visible client. - /// - IPlatformRunner PlatformRunner { get; } - } + IPlatformRunner PlatformRunner { get; } } diff --git a/Intersect.Client/Core/IPlatformRunner.cs b/Intersect.Client/Core/IPlatformRunner.cs index 7bc6567402..fe498f2bbe 100644 --- a/Intersect.Client/Core/IPlatformRunner.cs +++ b/Intersect.Client/Core/IPlatformRunner.cs @@ -1,15 +1,14 @@ -namespace Intersect.Client.Core +namespace Intersect.Client.Core; + +/// +/// Declares the API surface to launch instances of platform-specific (e.g. MonoGame, Unity) runners. +/// +internal interface IPlatformRunner { /// - /// Declares the API surface to launch instances of platform-specific (e.g. MonoGame, Unity) runners. + /// Starts the platform-specific runner for the provided context and post-startup action. /// - internal interface IPlatformRunner - { - /// - /// Starts the platform-specific runner for the provided context and post-startup action. - /// - /// the to run for - /// the to do after startup - void Start(IClientContext context, Action postStartupAction); - } + /// the to run for + /// the to do after startup + void Start(IClientContext context, Action postStartupAction); } diff --git a/Intersect.Client/Core/Input.cs b/Intersect.Client/Core/Input.cs index 1655f9e3a5..0f1aaf6105 100644 --- a/Intersect.Client/Core/Input.cs +++ b/Intersect.Client/Core/Input.cs @@ -11,525 +11,523 @@ using Intersect.Configuration; using Intersect.Utilities; -namespace Intersect.Client.Core +namespace Intersect.Client.Core; + +public static partial class Input { - public static partial class Input - { - public delegate void HandleKeyEvent(Keys modifier, Keys key); + public delegate void HandleKeyEvent(Keys modifier, Keys key); - public static HandleKeyEvent KeyDown; + public static HandleKeyEvent KeyDown; - public static HandleKeyEvent KeyUp; + public static HandleKeyEvent KeyUp; - public static HandleKeyEvent MouseDown; + public static HandleKeyEvent MouseDown; - public static HandleKeyEvent MouseUp; + public static HandleKeyEvent MouseUp; - private static void HandleZoomOut() + private static void HandleZoomOut() + { + Globals.Database.WorldZoom /= 2; + if (Globals.Database.WorldZoom < Graphics.BaseWorldScale) { - Globals.Database.WorldZoom /= 2; - if (Globals.Database.WorldZoom < Graphics.BaseWorldScale) - { - Globals.Database.WorldZoom = Graphics.BaseWorldScale * 4; - } + Globals.Database.WorldZoom = Graphics.BaseWorldScale * 4; } + } - private static void HandleZoomIn() + private static void HandleZoomIn() + { + Globals.Database.WorldZoom *= 2; + if (Globals.Database.WorldZoom > Graphics.BaseWorldScale * 4) { - Globals.Database.WorldZoom *= 2; - if (Globals.Database.WorldZoom > Graphics.BaseWorldScale * 4) - { - Globals.Database.WorldZoom = Graphics.BaseWorldScale; - } + Globals.Database.WorldZoom = Graphics.BaseWorldScale; } + } - public static void OnKeyPressed(Keys modifier, Keys key) + public static void OnKeyPressed(Keys modifier, Keys key) + { + if (key == Keys.None) { - if (key == Keys.None) - { - return; - } + return; + } - var consumeKey = false; - bool canFocusChat = true; + var consumeKey = false; + bool canFocusChat = true; - KeyDown?.Invoke(modifier, key); - switch (key) - { - case Keys.Escape: - if (Globals.GameState != GameStates.Intro) - { - break; - } + KeyDown?.Invoke(modifier, key); + switch (key) + { + case Keys.Escape: + if (Globals.GameState != GameStates.Intro) + { + break; + } - Fade.FadeIn(ClientConfiguration.Instance.FadeDurationMs); - Globals.GameState = GameStates.Menu; + Fade.FadeIn(ClientConfiguration.Instance.FadeDurationMs); + Globals.GameState = GameStates.Menu; - return; + return; - case Keys.Enter: + case Keys.Enter: - for (int i = Interface.Interface.InputBlockingElements.Count - 1; i >= 0; i--) + for (int i = Interface.Interface.InputBlockingElements.Count - 1; i >= 0; i--) + { + try { - try + var iBox = (InputBox)Interface.Interface.InputBlockingElements[i]; + if (iBox != null && !iBox.IsHidden) { - var iBox = (InputBox)Interface.Interface.InputBlockingElements[i]; - if (iBox != null && !iBox.IsHidden) - { - iBox.okayBtn_Clicked(null, null); - canFocusChat = false; + iBox.okayBtn_Clicked(null, null); + canFocusChat = false; - break; - } + break; } - catch { } + } + catch { } - try + try + { + var eventWindow = (EventWindow)Interface.Interface.InputBlockingElements[i]; + if (eventWindow != null && !eventWindow.IsHidden && Globals.EventDialogs.Count > 0) { - var eventWindow = (EventWindow)Interface.Interface.InputBlockingElements[i]; - if (eventWindow != null && !eventWindow.IsHidden && Globals.EventDialogs.Count > 0) - { - eventWindow.EventResponse1_Clicked(null, null); - canFocusChat = false; + eventWindow.EventResponse1_Clicked(null, null); + canFocusChat = false; - break; - } + break; } - catch { } } - - break; - } - - if (Controls.Controls.ControlHasKey(Control.OpenMenu, modifier, key)) - { - if (Globals.GameState != GameStates.InGame) - { - return; + catch { } } - // First try and unfocus chat then close all UI elements, then untarget our target.. and THEN open the escape menu. - // Most games do this, why not this? - if (Interface.Interface.GameUi != null && Interface.Interface.GameUi.ChatFocussed) - { - Interface.Interface.GameUi.UnfocusChat = true; - } - else if (Interface.Interface.GameUi != null && Interface.Interface.GameUi.CloseAllWindows()) - { - // We've closed our windows, don't do anything else. :) - } - else if (Globals.Me != null && Globals.Me.TargetIndex != Guid.Empty && !Globals.Me.Status.Any(s => s.Type == Enums.SpellEffect.Taunt)) - { - Globals.Me.ClearTarget(); - } - else - { - Interface.Interface.GameUi?.EscapeMenu?.ToggleHidden(); - } - } + break; + } - if (Interface.Interface.HasInputFocus()) + if (Controls.Controls.ControlHasKey(Control.OpenMenu, modifier, key)) + { + if (Globals.GameState != GameStates.InGame) { return; } - Controls.Controls.GetControlsFor(modifier, key) - ?.ForEach( - control => - { - if (consumeKey) - { - return; - } + // First try and unfocus chat then close all UI elements, then untarget our target.. and THEN open the escape menu. + // Most games do this, why not this? + if (Interface.Interface.GameUi != null && Interface.Interface.GameUi.ChatFocussed) + { + Interface.Interface.GameUi.UnfocusChat = true; + } + else if (Interface.Interface.GameUi != null && Interface.Interface.GameUi.CloseAllWindows()) + { + // We've closed our windows, don't do anything else. :) + } + else if (Globals.Me != null && Globals.Me.TargetIndex != Guid.Empty && !Globals.Me.Status.Any(s => s.Type == Enums.SpellEffect.Taunt)) + { + Globals.Me.ClearTarget(); + } + else + { + Interface.Interface.GameUi?.EscapeMenu?.ToggleHidden(); + } + } - if (IsModifier(key)) - { - return; - } + if (Interface.Interface.HasInputFocus()) + { + return; + } - switch (control) - { - case Control.Screenshot: - Graphics.Renderer?.RequestScreenshot(); + Controls.Controls.GetControlsFor(modifier, key) + ?.ForEach( + control => + { + if (consumeKey) + { + return; + } - break; + if (IsModifier(key)) + { + return; + } - case Control.ToggleGui: - if (Globals.GameState == GameStates.InGame) - { - Interface.Interface.HideUi = !Interface.Interface.HideUi; - } + switch (control) + { + case Control.Screenshot: + Graphics.Renderer?.RequestScreenshot(); - break; + break; - case Control.HoldToZoomIn: - case Control.ToggleZoomIn: + case Control.ToggleGui: + if (Globals.GameState == GameStates.InGame) { - HandleZoomIn(); - break; + Interface.Interface.HideUi = !Interface.Interface.HideUi; } - case Control.HoldToZoomOut: - case Control.ToggleZoomOut: - { - HandleZoomOut(); - break; - } + break; - case Control.ToggleFullscreen: - { - Globals.Database.FullScreen = !Globals.Database.FullScreen; - Globals.Database.SavePreferences(); - Graphics.Renderer.OverrideResolution = Resolution.Empty; - Graphics.Renderer.Init(); - break; - } + case Control.HoldToZoomIn: + case Control.ToggleZoomIn: + { + HandleZoomIn(); + break; + } - case Control.OpenDebugger: - MutableInterface.ToggleDebug(); - break; + case Control.HoldToZoomOut: + case Control.ToggleZoomOut: + { + HandleZoomOut(); + break; } - switch (Globals.GameState) + case Control.ToggleFullscreen: { - case GameStates.Intro: - break; + Globals.Database.FullScreen = !Globals.Database.FullScreen; + Globals.Database.SavePreferences(); + Graphics.Renderer.OverrideResolution = Resolution.Empty; + Graphics.Renderer.Init(); + break; + } - case GameStates.Menu: - break; + case Control.OpenDebugger: + MutableInterface.ToggleDebug(); + break; + } - case GameStates.InGame: - switch (control) - { - case Control.MoveUp: - break; + switch (Globals.GameState) + { + case GameStates.Intro: + break; - case Control.MoveLeft: - break; + case GameStates.Menu: + break; - case Control.MoveDown: - break; + case GameStates.InGame: + switch (control) + { + case Control.MoveUp: + break; - case Control.MoveRight: - break; + case Control.MoveLeft: + break; - case Control.AttackInteract: - break; + case Control.MoveDown: + break; - case Control.Block: - Globals.Me?.TryBlock(); + case Control.MoveRight: + break; - break; + case Control.AttackInteract: + break; - case Control.AutoTarget: - Globals.Me?.AutoTarget(); + case Control.Block: + Globals.Me?.TryBlock(); - break; + break; - case Control.PickUp: - Globals.Me?.TryPickupItem(Globals.Me.MapInstance.Id, Globals.Me.Y * Options.MapWidth + Globals.Me.X); + case Control.AutoTarget: + Globals.Me?.AutoTarget(); - break; + break; - case Control.Enter: - if (canFocusChat) - { - Interface.Interface.GameUi.FocusChat = true; - consumeKey = true; - } + case Control.PickUp: + Globals.Me?.TryPickupItem(Globals.Me.MapInstance.Id, Globals.Me.Y * Options.MapWidth + Globals.Me.X); - return; + break; - case Control.Hotkey1: - case Control.Hotkey2: - case Control.Hotkey3: - case Control.Hotkey4: - case Control.Hotkey5: - case Control.Hotkey6: - case Control.Hotkey7: - case Control.Hotkey8: - case Control.Hotkey9: - case Control.Hotkey0: - break; + case Control.Enter: + if (canFocusChat) + { + Interface.Interface.GameUi.FocusChat = true; + consumeKey = true; + } - case Control.OpenInventory: - Interface.Interface.GameUi?.GameMenu?.ToggleInventoryWindow(); + return; - break; + case Control.Hotkey1: + case Control.Hotkey2: + case Control.Hotkey3: + case Control.Hotkey4: + case Control.Hotkey5: + case Control.Hotkey6: + case Control.Hotkey7: + case Control.Hotkey8: + case Control.Hotkey9: + case Control.Hotkey0: + break; - case Control.OpenQuests: - Interface.Interface.GameUi?.GameMenu?.ToggleQuestsWindow(); + case Control.OpenInventory: + Interface.Interface.GameUi?.GameMenu?.ToggleInventoryWindow(); - break; + break; - case Control.OpenCharacterInfo: - Interface.Interface.GameUi?.GameMenu?.ToggleCharacterWindow(); + case Control.OpenQuests: + Interface.Interface.GameUi?.GameMenu?.ToggleQuestsWindow(); - break; + break; - case Control.OpenParties: - Interface.Interface.GameUi?.GameMenu?.TogglePartyWindow(); + case Control.OpenCharacterInfo: + Interface.Interface.GameUi?.GameMenu?.ToggleCharacterWindow(); - break; + break; - case Control.OpenSpells: - Interface.Interface.GameUi?.GameMenu?.ToggleSpellsWindow(); + case Control.OpenParties: + Interface.Interface.GameUi?.GameMenu?.TogglePartyWindow(); - break; + break; - case Control.OpenFriends: - Interface.Interface.GameUi?.GameMenu?.ToggleFriendsWindow(); + case Control.OpenSpells: + Interface.Interface.GameUi?.GameMenu?.ToggleSpellsWindow(); - break; + break; - case Control.OpenSettings: - Interface.Interface.GameUi?.EscapeMenu?.OpenSettingsWindow(); + case Control.OpenFriends: + Interface.Interface.GameUi?.GameMenu?.ToggleFriendsWindow(); - break; + break; - case Control.OpenAdminPanel: - PacketSender.SendOpenAdminWindow(); + case Control.OpenSettings: + Interface.Interface.GameUi?.EscapeMenu?.OpenSettingsWindow(); - break; + break; - case Control.OpenGuild: - Interface.Interface.GameUi?.GameMenu.ToggleGuildWindow(); + case Control.OpenAdminPanel: + PacketSender.SendOpenAdminWindow(); - break; - } + break; - break; + case Control.OpenGuild: + Interface.Interface.GameUi?.GameMenu.ToggleGuildWindow(); - case GameStates.Loading: - break; + break; + } - case GameStates.Error: - break; + break; - default: - throw new ArgumentOutOfRangeException( - nameof(Globals.GameState), Globals.GameState, null - ); - } + case GameStates.Loading: + break; + + case GameStates.Error: + break; + + default: + throw new ArgumentOutOfRangeException( + nameof(Globals.GameState), Globals.GameState, null + ); } - ); - } + } + ); + } - public static void OnKeyReleased(Keys modifier, Keys key) + public static void OnKeyReleased(Keys modifier, Keys key) + { + KeyUp?.Invoke(modifier, key); + if (Interface.Interface.HasInputFocus()) { - KeyUp?.Invoke(modifier, key); - if (Interface.Interface.HasInputFocus()) - { - return; - } + return; + } - if (Controls.Controls.ControlHasKey(Control.HoldToZoomIn, modifier, key)) - { - HandleZoomOut(); - } + if (Controls.Controls.ControlHasKey(Control.HoldToZoomIn, modifier, key)) + { + HandleZoomOut(); + } - if (Controls.Controls.ControlHasKey(Control.HoldToZoomOut, modifier, key)) - { - HandleZoomIn(); - } + if (Controls.Controls.ControlHasKey(Control.HoldToZoomOut, modifier, key)) + { + HandleZoomIn(); + } - if (Globals.Me == null) - { - return; - } + if (Globals.Me == null) + { + return; } + } - public static void OnMouseDown(Keys modifier, MouseButtons btn) + public static void OnMouseDown(Keys modifier, MouseButtons btn) + { + var key = Keys.None; + switch (btn) { - var key = Keys.None; - switch (btn) - { - case MouseButtons.Left: - key = Keys.LButton; + case MouseButtons.Left: + key = Keys.LButton; - break; + break; - case MouseButtons.Right: - key = Keys.RButton; + case MouseButtons.Right: + key = Keys.RButton; - break; + break; - case MouseButtons.Middle: - key = Keys.MButton; + case MouseButtons.Middle: + key = Keys.MButton; - break; - case MouseButtons.X1: - key = Keys.XButton1; + break; + case MouseButtons.X1: + key = Keys.XButton1; - break; - case MouseButtons.X2: - key = Keys.XButton2; + break; + case MouseButtons.X2: + key = Keys.XButton2; - break; - } + break; + } - MouseDown?.Invoke(modifier, key); - if (Interface.Interface.HasInputFocus()) - { - return; - } + MouseDown?.Invoke(modifier, key); + if (Interface.Interface.HasInputFocus()) + { + return; + } - if (Globals.GameState != GameStates.InGame || Globals.Me == null) - { - return; - } + if (Globals.GameState != GameStates.InGame || Globals.Me == null) + { + return; + } + + if (Interface.Interface.MouseHitGui()) + { + return; + } + + if (Globals.Me == null) + { + return; + } + + if (modifier == Keys.None && btn == MouseButtons.Left && Globals.Me.TryTarget()) + { + return; + } - if (Interface.Interface.MouseHitGui()) + if (Controls.Controls.ControlHasKey(Control.PickUp, modifier, key)) + { + if (Globals.Me.TryPickupItem(Globals.Me.MapInstance.Id, Globals.Me.Y * Options.MapWidth + Globals.Me.X, Guid.Empty, true)) { return; } - if (Globals.Me == null) + if (!Globals.Me.IsAttacking) { - return; + Globals.Me.AttackTimer = Timing.Global.Milliseconds + Globals.Me.CalculateAttackTime(); } + } - if (modifier == Keys.None && btn == MouseButtons.Left && Globals.Me.TryTarget()) + if (Controls.Controls.ControlHasKey(Control.Block, modifier, key)) + { + if (Globals.Me.TryBlock()) { return; } + } - if (Controls.Controls.ControlHasKey(Control.PickUp, modifier, key)) - { - if (Globals.Me.TryPickupItem(Globals.Me.MapInstance.Id, Globals.Me.Y * Options.MapWidth + Globals.Me.X, Guid.Empty, true)) - { - return; - } + if (key != Keys.None) + { + OnKeyPressed(modifier, key); + } + } - if (!Globals.Me.IsAttacking) - { - Globals.Me.AttackTimer = Timing.Global.Milliseconds + Globals.Me.CalculateAttackTime(); - } - } + public static void OnMouseUp(Keys modifier, MouseButtons btn) + { + var key = Keys.LButton; + switch (btn) + { + case MouseButtons.Right: + key = Keys.RButton; - if (Controls.Controls.ControlHasKey(Control.Block, modifier, key)) - { - if (Globals.Me.TryBlock()) - { - return; - } - } + break; - if (key != Keys.None) - { - OnKeyPressed(modifier, key); - } + case MouseButtons.Middle: + key = Keys.MButton; + + break; + case MouseButtons.X1: + key = Keys.XButton1; + + break; + case MouseButtons.X2: + key = Keys.XButton2; + + break; } - public static void OnMouseUp(Keys modifier, MouseButtons btn) + MouseUp?.Invoke(modifier, key); + if (Interface.Interface.HasInputFocus()) { - var key = Keys.LButton; - switch (btn) - { - case MouseButtons.Right: - key = Keys.RButton; + return; + } - break; + if (Controls.Controls.ControlHasKey(Control.HoldToZoomIn, modifier, key)) + { + HandleZoomOut(); + } - case MouseButtons.Middle: - key = Keys.MButton; + if (Controls.Controls.ControlHasKey(Control.HoldToZoomOut, modifier, key)) + { + HandleZoomIn(); + } - break; - case MouseButtons.X1: - key = Keys.XButton1; + if (Globals.Me == null) + { + return; + } - break; - case MouseButtons.X2: - key = Keys.XButton2; + if (btn != MouseButtons.Right) + { + return; + } - break; - } + if (Globals.InputManager.KeyDown(Keys.Shift) != true) + { + return; + } - MouseUp?.Invoke(modifier, key); - if (Interface.Interface.HasInputFocus()) - { - return; - } + var mouseInWorld = Graphics.ConvertToWorldPoint(Globals.InputManager.GetMousePosition()); + var x = (int)mouseInWorld.X; + var y = (int)mouseInWorld.Y; - if (Controls.Controls.ControlHasKey(Control.HoldToZoomIn, modifier, key)) + foreach (MapInstance map in MapInstance.Lookup.Values) + { + if (!(x >= map.GetX()) || !(x <= map.GetX() + Options.MapWidth * Options.TileWidth)) { - HandleZoomOut(); + continue; } - if (Controls.Controls.ControlHasKey(Control.HoldToZoomOut, modifier, key)) + if (!(y >= map.GetY()) || !(y <= map.GetY() + Options.MapHeight * Options.TileHeight)) { - HandleZoomIn(); + continue; } - if (Globals.Me == null) - { - return; - } + //Remove the offsets to just be dealing with pixels within the map selected + x -= (int) map.GetX(); + y -= (int) map.GetY(); - if (btn != MouseButtons.Right) - { - return; - } + //transform pixel format to tile format + x /= Options.TileWidth; + y /= Options.TileHeight; + var mapNum = map.Id; - if (Globals.InputManager.KeyDown(Keys.Shift) != true) + if (Globals.Me.TryGetRealLocation(ref x, ref y, ref mapNum)) { - return; + PacketSender.SendAdminAction(new WarpToLocationAction(map.Id, (byte) x, (byte) y)); } - var mouseInWorld = Graphics.ConvertToWorldPoint(Globals.InputManager.GetMousePosition()); - var x = (int)mouseInWorld.X; - var y = (int)mouseInWorld.Y; - - foreach (MapInstance map in MapInstance.Lookup.Values) - { - if (!(x >= map.GetX()) || !(x <= map.GetX() + Options.MapWidth * Options.TileWidth)) - { - continue; - } - - if (!(y >= map.GetY()) || !(y <= map.GetY() + Options.MapHeight * Options.TileHeight)) - { - continue; - } - - //Remove the offsets to just be dealing with pixels within the map selected - x -= (int) map.GetX(); - y -= (int) map.GetY(); - - //transform pixel format to tile format - x /= Options.TileWidth; - y /= Options.TileHeight; - var mapNum = map.Id; - - if (Globals.Me.TryGetRealLocation(ref x, ref y, ref mapNum)) - { - PacketSender.SendAdminAction(new WarpToLocationAction(map.Id, (byte) x, (byte) y)); - } - - return; - } + return; } + } - public static bool IsModifier(Keys key) + public static bool IsModifier(Keys key) + { + switch (key) { - switch (key) - { - case Keys.Control: - case Keys.ControlKey: - case Keys.LControlKey: - case Keys.RControlKey: - case Keys.LShiftKey: - case Keys.RShiftKey: - case Keys.Shift: - case Keys.ShiftKey: - case Keys.Alt: - return true; - - default: - return false; - } + case Keys.Control: + case Keys.ControlKey: + case Keys.LControlKey: + case Keys.RControlKey: + case Keys.LShiftKey: + case Keys.RShiftKey: + case Keys.Shift: + case Keys.ShiftKey: + case Keys.Alt: + return true; + + default: + return false; } } - } diff --git a/Intersect.Client/Core/Main.cs b/Intersect.Client/Core/Main.cs index 94631e0123..23122df88b 100644 --- a/Intersect.Client/Core/Main.cs +++ b/Intersect.Client/Core/Main.cs @@ -10,391 +10,389 @@ // ReSharper disable All -namespace Intersect.Client.Core -{ +namespace Intersect.Client.Core; - internal static partial class Main - { - private static long _animTimer; +internal static partial class Main +{ - private static bool _createdMapTextures; + private static long _animTimer; - private static bool _loadedTilesets; + private static bool _createdMapTextures; - internal static void Start(IClientContext context) - { - //Load Graphics - Graphics.InitGraphics(); + private static bool _loadedTilesets; - //Load Sounds - Audio.Init(); - Audio.PlayMusic(ClientConfiguration.Instance.MenuMusic, ClientConfiguration.Instance.MusicFadeTimer, ClientConfiguration.Instance.MusicFadeTimer, true); + internal static void Start(IClientContext context) + { + //Load Graphics + Graphics.InitGraphics(); - //Init Network - Networking.Network.InitNetwork(context); - Fade.FadeIn(ClientConfiguration.Instance.FadeDurationMs); + //Load Sounds + Audio.Init(); + Audio.PlayMusic(ClientConfiguration.Instance.MenuMusic, ClientConfiguration.Instance.MusicFadeTimer, ClientConfiguration.Instance.MusicFadeTimer, true); + + //Init Network + Networking.Network.InitNetwork(context); + Fade.FadeIn(ClientConfiguration.Instance.FadeDurationMs); - //Make Json.Net Familiar with Our Object Types - var id = Guid.NewGuid(); - foreach (var val in Enum.GetValues(typeof(GameObjectType))) + //Make Json.Net Familiar with Our Object Types + var id = Guid.NewGuid(); + foreach (var val in Enum.GetValues(typeof(GameObjectType))) + { + var type = ((GameObjectType) val); + if (type != GameObjectType.Event && type != GameObjectType.Time) { - var type = ((GameObjectType) val); - if (type != GameObjectType.Event && type != GameObjectType.Time) - { - var lookup = type.GetLookup(); - var item = lookup.AddNew(type.GetObjectType(), id); - item.Load(item.JsonData); - lookup.Delete(item); - } + var lookup = type.GetLookup(); + var item = lookup.AddNew(type.GetObjectType(), id); + item.Load(item.JsonData); + lookup.Delete(item); } } + } - public static void DestroyGame() - { - //Destroy Game - //TODO - Destroy Graphics and Networking peacefully - //Network.Close(); - Interface.Interface.DestroyGwen(true); - Graphics.Renderer.Close(); - } + public static void DestroyGame() + { + //Destroy Game + //TODO - Destroy Graphics and Networking peacefully + //Network.Close(); + Interface.Interface.DestroyGwen(true); + Graphics.Renderer.Close(); + } - public static void Update(TimeSpan deltaTime) + public static void Update(TimeSpan deltaTime) + { + lock (Globals.GameLock) { - lock (Globals.GameLock) - { - Networking.Network.Update(); - Fade.Update(); - Interface.Interface.ToggleInput(Globals.GameState != GameStates.Intro); + Networking.Network.Update(); + Fade.Update(); + Interface.Interface.ToggleInput(Globals.GameState != GameStates.Intro); - switch (Globals.GameState) - { - case GameStates.Intro: - ProcessIntro(); + switch (Globals.GameState) + { + case GameStates.Intro: + ProcessIntro(); - break; + break; - case GameStates.Menu: - ProcessMenu(); + case GameStates.Menu: + ProcessMenu(); - break; + break; - case GameStates.Loading: - ProcessLoading(); + case GameStates.Loading: + ProcessLoading(); - break; + break; - case GameStates.InGame: - ProcessGame(); + case GameStates.InGame: + ProcessGame(); - break; + break; - case GameStates.Error: - break; + case GameStates.Error: + break; - default: - throw new ArgumentOutOfRangeException( - nameof(Globals.GameState), $"Value {Globals.GameState} out of range." - ); - } + default: + throw new ArgumentOutOfRangeException( + nameof(Globals.GameState), $"Value {Globals.GameState} out of range." + ); + } - Globals.InputManager.Update(deltaTime); - Audio.Update(); + Globals.InputManager.Update(deltaTime); + Audio.Update(); - Globals.OnGameUpdate(deltaTime); - } + Globals.OnGameUpdate(deltaTime); } + } - private static void ProcessIntro() + private static void ProcessIntro() + { + if (ClientConfiguration.Instance.IntroImages.Count > 0) { - if (ClientConfiguration.Instance.IntroImages.Count > 0) - { - GameTexture imageTex = Globals.ContentManager.GetTexture( - Framework.Content.TextureType.Image, ClientConfiguration.Instance.IntroImages[Globals.IntroIndex] - ); + GameTexture imageTex = Globals.ContentManager.GetTexture( + Framework.Content.TextureType.Image, ClientConfiguration.Instance.IntroImages[Globals.IntroIndex] + ); - if (imageTex != null) + if (imageTex != null) + { + if (Globals.IntroStartTime == -1) { - if (Globals.IntroStartTime == -1) + if (Fade.DoneFading()) { - if (Fade.DoneFading()) + if (Globals.IntroComing) { - if (Globals.IntroComing) - { - Globals.IntroStartTime = Timing.Global.MillisecondsUtc; - } - else - { - Globals.IntroIndex++; - Fade.FadeIn(ClientConfiguration.Instance.FadeDurationMs); - Globals.IntroComing = true; - } + Globals.IntroStartTime = Timing.Global.MillisecondsUtc; } - } - else - { - if (Timing.Global.MillisecondsUtc > Globals.IntroStartTime + Globals.IntroDelay) + else { - //If we have shown an image long enough, fade to black -- keep track that the image is going - Fade.FadeOut(ClientConfiguration.Instance.FadeDurationMs); - Globals.IntroStartTime = -1; - Globals.IntroComing = false; + Globals.IntroIndex++; + Fade.FadeIn(ClientConfiguration.Instance.FadeDurationMs); + Globals.IntroComing = true; } } } else { - Globals.IntroIndex++; - } - - if (Globals.IntroIndex >= ClientConfiguration.Instance.IntroImages.Count) - { - Globals.GameState = GameStates.Menu; + if (Timing.Global.MillisecondsUtc > Globals.IntroStartTime + Globals.IntroDelay) + { + //If we have shown an image long enough, fade to black -- keep track that the image is going + Fade.FadeOut(ClientConfiguration.Instance.FadeDurationMs); + Globals.IntroStartTime = -1; + Globals.IntroComing = false; + } } } else + { + Globals.IntroIndex++; + } + + if (Globals.IntroIndex >= ClientConfiguration.Instance.IntroImages.Count) { Globals.GameState = GameStates.Menu; } } - - private static void ProcessMenu() + else { - if (!Globals.JoiningGame) - return; - - //if (GameGraphics.FadeAmt != 255f) return; - //Check if maps are loaded and ready - Globals.GameState = GameStates.Loading; - Interface.Interface.DestroyGwen(); + Globals.GameState = GameStates.Menu; } + } - private static void ProcessLoading() - { - if (Globals.Me == null || Globals.Me.MapInstance == null) - return; + private static void ProcessMenu() + { + if (!Globals.JoiningGame) + return; - if (!_loadedTilesets && Globals.HasGameData) - { - Globals.ContentManager.LoadTilesets(TilesetBase.GetNameList()); - _loadedTilesets = true; - } + //if (GameGraphics.FadeAmt != 255f) return; + //Check if maps are loaded and ready + Globals.GameState = GameStates.Loading; + Interface.Interface.DestroyGwen(); + } - Audio.PlayMusic(MapInstance.Get(Globals.Me.MapId).Music, ClientConfiguration.Instance.MusicFadeTimer, ClientConfiguration.Instance.MusicFadeTimer, true); - Globals.GameState = GameStates.InGame; - Fade.FadeIn(ClientConfiguration.Instance.FadeDurationMs); + private static void ProcessLoading() + { + if (Globals.Me == null || Globals.Me.MapInstance == null) + return; + + if (!_loadedTilesets && Globals.HasGameData) + { + Globals.ContentManager.LoadTilesets(TilesetBase.GetNameList()); + _loadedTilesets = true; } - private static void ProcessGame() + Audio.PlayMusic(MapInstance.Get(Globals.Me.MapId).Music, ClientConfiguration.Instance.MusicFadeTimer, ClientConfiguration.Instance.MusicFadeTimer, true); + Globals.GameState = GameStates.InGame; + Fade.FadeIn(ClientConfiguration.Instance.FadeDurationMs); + } + + private static void ProcessGame() + { + if (Globals.ConnectionLost) { - if (Globals.ConnectionLost) - { - Logout(false); - Globals.ConnectionLost = false; - return; - } + Logout(false); + Globals.ConnectionLost = false; + return; + } - //If we are waiting on maps, lets see if we have them - if (Globals.NeedsMaps) + //If we are waiting on maps, lets see if we have them + if (Globals.NeedsMaps) + { + bool canShowWorld = true; + if (MapInstance.TryGet(Globals.Me.MapId, out var mapInstance)) { - bool canShowWorld = true; - if (MapInstance.TryGet(Globals.Me.MapId, out var mapInstance)) + var gridX = mapInstance.GridX; + var gridY = mapInstance.GridY; + for (int x = gridX - 1; x <= gridX + 1; x++) { - var gridX = mapInstance.GridX; - var gridY = mapInstance.GridY; - for (int x = gridX - 1; x <= gridX + 1; x++) + for (int y = gridY - 1; y <= gridY + 1; y++) { - for (int y = gridY - 1; y <= gridY + 1; y++) + if (x >= 0 && + x < Globals.MapGridWidth && + y >= 0 && + y < Globals.MapGridHeight && + Globals.MapGrid[x, y] != Guid.Empty) { - if (x >= 0 && - x < Globals.MapGridWidth && - y >= 0 && - y < Globals.MapGridHeight && - Globals.MapGrid[x, y] != Guid.Empty) + var map = MapInstance.Get(Globals.MapGrid[x, y]); + if (map != null) { - var map = MapInstance.Get(Globals.MapGrid[x, y]); - if (map != null) - { - if (!map.IsLoaded) - { - canShowWorld = false; - } - } - else + if (!map.IsLoaded) { canShowWorld = false; } } + else + { + canShowWorld = false; + } } } } - else - { - canShowWorld = false; - } - - canShowWorld = true; - if (canShowWorld) - { - Globals.NeedsMaps = false; - //Send ping to server, so it will resync time if needed as we load in - PacketSender.SendPing(); - } } else { - PacketSender.SendNeedMapForGrid(); + canShowWorld = false; } - if (!Globals.NeedsMaps) + canShowWorld = true; + if (canShowWorld) { - //Update All Entities - foreach (var en in Globals.Entities) - { - if (en.Value == null) - continue; - - en.Value.Update(); - } - - for (int i = 0; i < Globals.EntitiesToDispose.Count; i++) - { - if (Globals.Entities.ContainsKey(Globals.EntitiesToDispose[i])) - { - if (Globals.EntitiesToDispose[i] == Globals.Me.Id) - continue; + Globals.NeedsMaps = false; + //Send ping to server, so it will resync time if needed as we load in + PacketSender.SendPing(); + } + } + else + { + PacketSender.SendNeedMapForGrid(); + } - Globals.Entities[Globals.EntitiesToDispose[i]].Dispose(); - Globals.Entities.Remove(Globals.EntitiesToDispose[i]); - } - } + if (!Globals.NeedsMaps) + { + //Update All Entities + foreach (var en in Globals.Entities) + { + if (en.Value == null) + continue; - Globals.EntitiesToDispose.Clear(); + en.Value.Update(); + } - //Update Maps - var maps = MapInstance.Lookup.Values.ToArray(); - foreach (MapInstance map in maps) + for (int i = 0; i < Globals.EntitiesToDispose.Count; i++) + { + if (Globals.Entities.ContainsKey(Globals.EntitiesToDispose[i])) { - if (map == null) + if (Globals.EntitiesToDispose[i] == Globals.Me.Id) continue; - map.Update(map.InView()); + Globals.Entities[Globals.EntitiesToDispose[i]].Dispose(); + Globals.Entities.Remove(Globals.EntitiesToDispose[i]); } } - //Update Game Animations - if (_animTimer < Timing.Global.MillisecondsUtc) + Globals.EntitiesToDispose.Clear(); + + //Update Maps + var maps = MapInstance.Lookup.Values.ToArray(); + foreach (MapInstance map in maps) { - Globals.AnimFrame++; - if (Globals.AnimFrame == 3) - { - Globals.AnimFrame = 0; - } + if (map == null) + continue; - _animTimer = Timing.Global.MillisecondsUtc + 500; + map.Update(map.InView()); } + } - //Remove Event Holds If Invalid - var removeHolds = new List(); - foreach (var hold in Globals.EventHolds) + //Update Game Animations + if (_animTimer < Timing.Global.MillisecondsUtc) + { + Globals.AnimFrame++; + if (Globals.AnimFrame == 3) { - //If hold.value is empty its a common event, ignore. Otherwise make sure we have the map else the hold doesnt matter - if (hold.Value != Guid.Empty && MapInstance.Get(hold.Value) == null) - { - removeHolds.Add(hold.Key); - } + Globals.AnimFrame = 0; } - foreach (var hold in removeHolds) + _animTimer = Timing.Global.MillisecondsUtc + 500; + } + + //Remove Event Holds If Invalid + var removeHolds = new List(); + foreach (var hold in Globals.EventHolds) + { + //If hold.value is empty its a common event, ignore. Otherwise make sure we have the map else the hold doesnt matter + if (hold.Value != Guid.Empty && MapInstance.Get(hold.Value) == null) { - Globals.EventHolds.Remove(hold); + removeHolds.Add(hold.Key); } - - Graphics.UpdatePlayerLight(); - Time.Update(); } - public static void JoinGame() + foreach (var hold in removeHolds) { - Globals.LoggedIn = true; - Audio.StopMusic(ClientConfiguration.Instance.MusicFadeTimer); + Globals.EventHolds.Remove(hold); } - public static void Logout(bool characterSelect, bool skipFade = false) - { - Audio.PlayMusic(ClientConfiguration.Instance.MenuMusic, ClientConfiguration.Instance.MusicFadeTimer, ClientConfiguration.Instance.MusicFadeTimer, true); - if (skipFade) - { - Fade.Cancel(); - } - else - { - Fade.FadeOut(ClientConfiguration.Instance.FadeDurationMs); - } + Graphics.UpdatePlayerLight(); + Time.Update(); + } - if (!ClientContext.IsSinglePlayer) - { - Globals.SoftLogout = !characterSelect; - PacketSender.SendLogout(characterSelect); - } + public static void JoinGame() + { + Globals.LoggedIn = true; + Audio.StopMusic(ClientConfiguration.Instance.MusicFadeTimer); + } - Globals.LoggedIn = false; - Globals.WaitingOnServer = false; - Globals.GameState = GameStates.Menu; - Globals.JoiningGame = false; - Globals.NeedsMaps = true; - Globals.Picture = null; - - Globals.InBag = false; - Globals.InBank = false; - Globals.GameShop = null; - Globals.InTrade = false; - Globals.EventDialogs?.Clear(); - Globals.InCraft = false; - - Interface.Interface.HideUi = false; - - //Dump Game Objects - Globals.Me = null; - Globals.HasGameData = false; - foreach (var map in MapInstance.Lookup) - { - var mp = (MapInstance) map.Value; - mp.Dispose(false, true); - } + public static void Logout(bool characterSelect, bool skipFade = false) + { + Audio.PlayMusic(ClientConfiguration.Instance.MenuMusic, ClientConfiguration.Instance.MusicFadeTimer, ClientConfiguration.Instance.MusicFadeTimer, true); + if (skipFade) + { + Fade.Cancel(); + } + else + { + Fade.FadeOut(ClientConfiguration.Instance.FadeDurationMs); + } - foreach (var en in Globals.Entities.ToArray()) - { - en.Value.Dispose(); - } + if (!ClientContext.IsSinglePlayer) + { + Globals.SoftLogout = !characterSelect; + PacketSender.SendLogout(characterSelect); + } - MapBase.Lookup.Clear(); - MapInstance.Lookup.Clear(); + Globals.LoggedIn = false; + Globals.WaitingOnServer = false; + Globals.GameState = GameStates.Menu; + Globals.JoiningGame = false; + Globals.NeedsMaps = true; + Globals.Picture = null; + + Globals.InBag = false; + Globals.InBank = false; + Globals.GameShop = null; + Globals.InTrade = false; + Globals.EventDialogs?.Clear(); + Globals.InCraft = false; + + Interface.Interface.HideUi = false; + + //Dump Game Objects + Globals.Me = null; + Globals.HasGameData = false; + foreach (var map in MapInstance.Lookup) + { + var mp = (MapInstance) map.Value; + mp.Dispose(false, true); + } - Globals.Entities.Clear(); - Globals.MapGrid = null; - Globals.GridMaps.Clear(); - Globals.EventDialogs.Clear(); - Globals.EventHolds.Clear(); - Globals.PendingEvents.Clear(); + foreach (var en in Globals.Entities.ToArray()) + { + en.Value.Dispose(); + } - Interface.Interface.InitGwen(); + MapBase.Lookup.Clear(); + MapInstance.Lookup.Clear(); - if (ClientContext.IsSinglePlayer) - { - PacketSender.SendLogout(characterSelect); - } + Globals.Entities.Clear(); + Globals.MapGrid = null; + Globals.GridMaps.Clear(); + Globals.EventDialogs.Clear(); + Globals.EventHolds.Clear(); + Globals.PendingEvents.Clear(); - if (skipFade) - { - Fade.Cancel(); - } - else - { - Fade.FadeIn(ClientConfiguration.Instance.FadeDurationMs); - } + Interface.Interface.InitGwen(); + + if (ClientContext.IsSinglePlayer) + { + PacketSender.SendLogout(characterSelect); } + if (skipFade) + { + Fade.Cancel(); + } + else + { + Fade.FadeIn(ClientConfiguration.Instance.FadeDurationMs); + } } } diff --git a/Intersect.Client/Core/Sounds/MapSound.cs b/Intersect.Client/Core/Sounds/MapSound.cs index 7436c5829f..283456465b 100644 --- a/Intersect.Client/Core/Sounds/MapSound.cs +++ b/Intersect.Client/Core/Sounds/MapSound.cs @@ -4,265 +4,263 @@ using Intersect.Client.General; using Intersect.Client.Maps; -namespace Intersect.Client.Core.Sounds -{ +namespace Intersect.Client.Core.Sounds; - public partial class MapSound : Sound, IMapSound - { - private int mDistance; +public partial class MapSound : Sound, IMapSound +{ - private IEntity mEntity; + private int mDistance; - private Guid mMapId; + private IEntity mEntity; - private int mX; + private Guid mMapId; - private int mY; + private int mX; - public MapSound( - string filename, - int x, - int y, - Guid mapId, - bool loop, - int loopInterval, - int distance, - IEntity parent = null - ) : base(filename, loop, loopInterval) - { - if (string.IsNullOrEmpty(filename) || mSound == null) - { - return; - } + private int mY; - mDistance = distance; - mX = x; - mY = y; - mMapId = mapId; - mEntity = parent; - mSound.SetVolume(0); - } - - public void UpdatePosition(int x, int y, Guid mapId) + public MapSound( + string filename, + int x, + int y, + Guid mapId, + bool loop, + int loopInterval, + int distance, + IEntity parent = null + ) : base(filename, loop, loopInterval) + { + if (string.IsNullOrEmpty(filename) || mSound == null) { - mX = x; - mY = y; - mMapId = mapId; + return; } - public override bool Update() - { - if (base.Update()) - { - UpdateSoundVolume(); + mDistance = distance; + mX = x; + mY = y; + mMapId = mapId; + mEntity = parent; + mSound.SetVolume(0); + } - return true; - } + public void UpdatePosition(int x, int y, Guid mapId) + { + mX = x; + mY = y; + mMapId = mapId; + } + + public override bool Update() + { + if (base.Update()) + { + UpdateSoundVolume(); - return false; + return true; } - private void UpdateSoundVolume() + return false; + } + + private void UpdateSoundVolume() + { + if (mMapId == Guid.Empty) { - if (mMapId == Guid.Empty) - { - mSound.SetVolume(0); + mSound.SetVolume(0); - return; - } + return; + } - var map = MapInstance.Get(mMapId); - if (map == null && mEntity != Globals.Me || Globals.Me == null) - { - Stop(); + var map = MapInstance.Get(mMapId); + if (map == null && mEntity != Globals.Me || Globals.Me == null) + { + Stop(); - return; - } + return; + } - var sameMap = mMapId == Globals.Me.MapId; - var inGrid = sameMap; - if (!inGrid && Globals.Me.MapInstance != null) + var sameMap = mMapId == Globals.Me.MapId; + var inGrid = sameMap; + if (!inGrid && Globals.Me.MapInstance != null) + { + var gridX = Globals.Me.MapInstance.GridX; + var gridY = Globals.Me.MapInstance.GridY; + for (var x = gridX - 1; x <= gridX + 1; x++) { - var gridX = Globals.Me.MapInstance.GridX; - var gridY = Globals.Me.MapInstance.GridY; - for (var x = gridX - 1; x <= gridX + 1; x++) + for (var y = gridY - 1; y <= gridY + 1; y++) { - for (var y = gridY - 1; y <= gridY + 1; y++) + if (x >= 0 && + x < Globals.MapGridWidth && + y >= 0 && + y < Globals.MapGridHeight && + Globals.MapGrid[x, y] != Guid.Empty) { - if (x >= 0 && - x < Globals.MapGridWidth && - y >= 0 && - y < Globals.MapGridHeight && - Globals.MapGrid[x, y] != Guid.Empty) + if (Globals.MapGrid[x, y] == mMapId) { - if (Globals.MapGrid[x, y] == mMapId) - { - inGrid = true; + inGrid = true; - break; - } + break; } } } } + } - if ((mX == -1 || mY == -1 || mDistance <= 0) && sameMap) + if ((mX == -1 || mY == -1 || mDistance <= 0) && sameMap) + { + mSound.SetVolume(100); + } + else + { + if (mDistance > 0 && Globals.GridMaps.Contains(mMapId)) { - mSound.SetVolume(100); + var volume = 100 - 100 / (mDistance + 1) * CalculateSoundDistance(); + if (volume < 0) + { + volume = 0f; + } + + mSound.SetVolume((int)volume); } else { - if (mDistance > 0 && Globals.GridMaps.Contains(mMapId)) - { - var volume = 100 - 100 / (mDistance + 1) * CalculateSoundDistance(); - if (volume < 0) - { - volume = 0f; - } - - mSound.SetVolume((int)volume); - } - else - { - mSound.SetVolume(0); - } + mSound.SetVolume(0); } } + } - private float CalculateSoundDistance() + private float CalculateSoundDistance() + { + var distance = 0f; + var playerx = 0f; + var playery = 0f; + float soundx = 0; + float soundy = 0; + var map = MapInstance.Get(mMapId); + var pMap = MapInstance.Get(Globals.Me.MapId); + if (map != null && pMap != null) { - var distance = 0f; - var playerx = 0f; - var playery = 0f; - float soundx = 0; - float soundy = 0; - var map = MapInstance.Get(mMapId); - var pMap = MapInstance.Get(Globals.Me.MapId); - if (map != null && pMap != null) + playerx = pMap.GetX() + Globals.Me.X * Options.TileWidth + (Options.TileWidth / 2); + playery = pMap.GetY() + Globals.Me.Y * Options.TileHeight + (Options.TileHeight / 2); + if (mX == -1 || mY == -1 || mDistance == -1) { - playerx = pMap.GetX() + Globals.Me.X * Options.TileWidth + (Options.TileWidth / 2); - playery = pMap.GetY() + Globals.Me.Y * Options.TileHeight + (Options.TileHeight / 2); - if (mX == -1 || mY == -1 || mDistance == -1) - { - var player = new Point() { - X = (int)playerx, - Y = (int)playery - }; - - var mapRect = new Rectangle( - (int)map.GetX(), (int)map.GetY(), Options.MapWidth * Options.TileWidth, - Options.MapHeight * Options.TileHeight - ); - - distance = DistancePointToRectangle(player, mapRect) / - ((Options.TileHeight + Options.TileWidth) / 2f); - } - else - { - soundx = map.GetX() + mX * Options.TileWidth + (Options.TileWidth / 2); - soundy = map.GetY() + mY * Options.TileHeight + (Options.TileHeight / 2); - distance = (float) Math.Sqrt(Math.Pow(playerx - soundx, 2) + Math.Pow(playery - soundy, 2)) / - ((Options.TileHeight + Options.TileWidth) / 2f); - } + var player = new Point() { + X = (int)playerx, + Y = (int)playery + }; + + var mapRect = new Rectangle( + (int)map.GetX(), (int)map.GetY(), Options.MapWidth * Options.TileWidth, + Options.MapHeight * Options.TileHeight + ); + + distance = DistancePointToRectangle(player, mapRect) / + ((Options.TileHeight + Options.TileWidth) / 2f); + } + else + { + soundx = map.GetX() + mX * Options.TileWidth + (Options.TileWidth / 2); + soundy = map.GetY() + mY * Options.TileHeight + (Options.TileHeight / 2); + distance = (float) Math.Sqrt(Math.Pow(playerx - soundx, 2) + Math.Pow(playery - soundy, 2)) / + ((Options.TileHeight + Options.TileWidth) / 2f); } - - return distance; } - //Code Courtesy of Philip Peterson. -- Released under MIT license. - //Obtained, 06/27/2015 from http://wiki.unity3d.com/index.php/Distance_from_a_point_to_a_rectangle - public static float DistancePointToRectangle(Point point, Rectangle rect) + return distance; + } + + //Code Courtesy of Philip Peterson. -- Released under MIT license. + //Obtained, 06/27/2015 from http://wiki.unity3d.com/index.php/Distance_from_a_point_to_a_rectangle + public static float DistancePointToRectangle(Point point, Rectangle rect) + { + // Calculate a distance between a point and a rectangle. + // The area around/in the rectangle is defined in terms of + // several regions: + // + // O--x + // | + // y + // + // + // I | II | III + // ======+==========+====== --yMin + // VIII | IX (in) | IV + // ======+==========+====== --yMax + // VII | VI | V + // + // + // Note that the +y direction is down because of Unity's GUI coordinates. + + if (point.X < rect.X) { - // Calculate a distance between a point and a rectangle. - // The area around/in the rectangle is defined in terms of - // several regions: - // - // O--x - // | - // y - // - // - // I | II | III - // ======+==========+====== --yMin - // VIII | IX (in) | IV - // ======+==========+====== --yMax - // VII | VI | V - // - // - // Note that the +y direction is down because of Unity's GUI coordinates. - - if (point.X < rect.X) + // Region I, VIII, or VII + if (point.Y < rect.Y) { - // Region I, VIII, or VII - if (point.Y < rect.Y) - { - // I - point.X = point.X - rect.X; - point.Y = point.Y - rect.Y; + // I + point.X = point.X - rect.X; + point.Y = point.Y - rect.Y; - return (float)Math.Sqrt(point.X * point.X + point.Y * point.Y); - } - else if (point.Y > rect.Y + rect.Height) - { - // VII - point.X = point.X - rect.X; - point.Y = point.Y - (rect.Y + rect.Height); + return (float)Math.Sqrt(point.X * point.X + point.Y * point.Y); + } + else if (point.Y > rect.Y + rect.Height) + { + // VII + point.X = point.X - rect.X; + point.Y = point.Y - (rect.Y + rect.Height); - return (float)Math.Sqrt(point.X * point.X + point.Y * point.Y); - } - else - { - // VIII - return rect.X - point.X; - } + return (float)Math.Sqrt(point.X * point.X + point.Y * point.Y); } - else if (point.X > rect.X + rect.Width) + else { - // Region III, IV, or V - if (point.Y < rect.Y) - { - // III - point.X = point.X - (rect.X + rect.Width); - point.Y = point.Y - rect.Y; + // VIII + return rect.X - point.X; + } + } + else if (point.X > rect.X + rect.Width) + { + // Region III, IV, or V + if (point.Y < rect.Y) + { + // III + point.X = point.X - (rect.X + rect.Width); + point.Y = point.Y - rect.Y; - return (float)Math.Sqrt(point.X * point.X + point.Y * point.Y); - } - else if (point.Y > rect.Y + rect.Height) - { - // V - point.X = point.X - (rect.X + rect.Width); - point.Y = point.Y - (rect.Y + rect.Height); + return (float)Math.Sqrt(point.X * point.X + point.Y * point.Y); + } + else if (point.Y > rect.Y + rect.Height) + { + // V + point.X = point.X - (rect.X + rect.Width); + point.Y = point.Y - (rect.Y + rect.Height); - return (float)Math.Sqrt(point.X * point.X + point.Y * point.Y); - } - else - { - // IV - return point.X - (rect.X + rect.Width); - } + return (float)Math.Sqrt(point.X * point.X + point.Y * point.Y); } else { - // Region II, IX, or VI - if (point.Y < rect.Y) - { - // II - return rect.Y - point.Y; - } - else if (point.Y > rect.Y + rect.Height) - { - // VI - return point.Y - (rect.Y + rect.Height); - } - else - { - // IX - return 0f; - } + // IV + return point.X - (rect.X + rect.Width); + } + } + else + { + // Region II, IX, or VI + if (point.Y < rect.Y) + { + // II + return rect.Y - point.Y; + } + else if (point.Y > rect.Y + rect.Height) + { + // VI + return point.Y - (rect.Y + rect.Height); + } + else + { + // IX + return 0f; } } - } } diff --git a/Intersect.Client/Core/Sounds/Sound.cs b/Intersect.Client/Core/Sounds/Sound.cs index 7c93551f40..0a8a1f2f7b 100644 --- a/Intersect.Client/Core/Sounds/Sound.cs +++ b/Intersect.Client/Core/Sounds/Sound.cs @@ -4,107 +4,105 @@ using Intersect.Client.General; using Intersect.Utilities; -namespace Intersect.Client.Core.Sounds +namespace Intersect.Client.Core.Sounds; + + +public partial class Sound : ISound { - public partial class Sound : ISound - { + public bool Loaded { get; set; } - public bool Loaded { get; set; } + protected string mFilename; - protected string mFilename; + public string Filename => mFilename; - public string Filename => mFilename; + protected bool mLoop; - protected bool mLoop; + protected int mLoopInterval; - protected int mLoopInterval; + protected GameAudioInstance mSound; - protected GameAudioInstance mSound; + protected float mVolume; - protected float mVolume; + private long mStoppedTime = -1; - private long mStoppedTime = -1; + public Sound(string filename, bool loop, int loopInterval) + { + if (string.IsNullOrWhiteSpace(filename)) + { + return; + } - public Sound(string filename, bool loop, int loopInterval) + mFilename = GameContentManager.RemoveExtension(filename).ToLower(); + mLoop = loop; + mLoopInterval = loopInterval; + var sound = Globals.ContentManager.GetSound(mFilename); + if (sound != null) { - if (string.IsNullOrWhiteSpace(filename)) - { - return; - } + mSound = sound.CreateInstance(); + mSound.IsLooping = mLoop && mLoopInterval <= 0; + + mSound.SetVolume(100); + mSound.Play(); + Loaded = true; + } + } - mFilename = GameContentManager.RemoveExtension(filename).ToLower(); - mLoop = loop; - mLoopInterval = loopInterval; - var sound = Globals.ContentManager.GetSound(mFilename); - if (sound != null) + public bool Loop + { + get => mLoop; + set + { + mLoop = value; + if (mSound != null) { - mSound = sound.CreateInstance(); - mSound.IsLooping = mLoop && mLoopInterval <= 0; - - mSound.SetVolume(100); - mSound.Play(); - Loaded = true; + mSound.IsLooping = mLoop; } } + } - public bool Loop + public virtual bool Update() + { + if (!Loaded) { - get => mLoop; - set - { - mLoop = value; - if (mSound != null) - { - mSound.IsLooping = mLoop; - } - } + return false; } - public virtual bool Update() + if (mLoop && mLoopInterval > 0 && mSound?.State == GameAudioInstance.AudioInstanceState.Stopped) { - if (!Loaded) + if (mStoppedTime == -1) { - return false; + mStoppedTime = Timing.Global.MillisecondsUtc; } - - if (mLoop && mLoopInterval > 0 && mSound?.State == GameAudioInstance.AudioInstanceState.Stopped) + else { - if (mStoppedTime == -1) - { - mStoppedTime = Timing.Global.MillisecondsUtc; - } - else + if (mStoppedTime + mLoopInterval < Timing.Global.MillisecondsUtc) { - if (mStoppedTime + mLoopInterval < Timing.Global.MillisecondsUtc) - { - mSound.Play(); - mStoppedTime = -1; - } + mSound.Play(); + mStoppedTime = -1; } - return true; - } - else if (mLoop || mSound?.State != GameAudioInstance.AudioInstanceState.Stopped) - { - return true; } + return true; + } + else if (mLoop || mSound?.State != GameAudioInstance.AudioInstanceState.Stopped) + { + return true; + } - Stop(); + Stop(); - return false; - } + return false; + } - public virtual void Stop() + public virtual void Stop() + { + if (!Loaded) { - if (!Loaded) - { - return; - } - - mSound?.Dispose(); - Loaded = false; + return; } + mSound?.Dispose(); + Loaded = false; } } diff --git a/Intersect.Client/Entities/Animation.cs b/Intersect.Client/Entities/Animation.cs index 1b11bbbde3..9dc7de1211 100644 --- a/Intersect.Client/Entities/Animation.cs +++ b/Intersect.Client/Entities/Animation.cs @@ -8,481 +8,479 @@ using Intersect.GameObjects; using Intersect.Utilities; -namespace Intersect.Client.Entities -{ +namespace Intersect.Client.Entities; - public partial class Animation : IAnimation - { - public bool AutoRotate { get; set; } +public partial class Animation : IAnimation +{ - private bool disposed = false; + public bool AutoRotate { get; set; } - public bool Hidden { get; set; } + private bool disposed = false; - public bool InfiniteLoop { get; set; } + public bool Hidden { get; set; } - private bool mDisposeNextDraw; + public bool InfiniteLoop { get; set; } - private int mLowerFrame; + private bool mDisposeNextDraw; - private int mLowerLoop; + private int mLowerFrame; - private long mLowerTimer; + private int mLowerLoop; - private Entity mParent; + private long mLowerTimer; - private Direction mRenderDir; + private Entity mParent; - private float mRenderX; + private Direction mRenderDir; - private float mRenderY; + private float mRenderX; - private bool mShowLower = true; + private float mRenderY; - private bool mShowUpper = true; + private bool mShowLower = true; - private MapSound mSound; + private bool mShowUpper = true; - private long mStartTime = Timing.Global.MillisecondsUtc; + private MapSound mSound; - private int mUpperFrame; + private long mStartTime = Timing.Global.MillisecondsUtc; - private int mUpperLoop; + private int mUpperFrame; - private long mUpperTimer; + private int mUpperLoop; - private bool mUseExternalRotation; + private long mUpperTimer; - private float mExternalRotation; + private bool mUseExternalRotation; - public AnimationBase MyBase { get; set; } + private float mExternalRotation; - public Point Size => CalculateAnimationSize(); + public AnimationBase MyBase { get; set; } - private int mZDimension = -1; + public Point Size => CalculateAnimationSize(); - public Animation( - AnimationBase animBase, - bool loopForever, - bool autoRotate = false, - int zDimension = -1, - Entity parent = null - ) + private int mZDimension = -1; + + public Animation( + AnimationBase animBase, + bool loopForever, + bool autoRotate = false, + int zDimension = -1, + Entity parent = null + ) + { + MyBase = animBase; + mParent = parent; + if (MyBase != null) { - MyBase = animBase; - mParent = parent; - if (MyBase != null) + mLowerLoop = animBase.Lower.LoopCount; + mUpperLoop = animBase.Upper.LoopCount; + mLowerTimer = Timing.Global.MillisecondsUtc + animBase.Lower.FrameSpeed; + mUpperTimer = Timing.Global.MillisecondsUtc + animBase.Upper.FrameSpeed; + InfiniteLoop = loopForever; + AutoRotate = autoRotate; + mZDimension = zDimension; + mSound = Audio.AddMapSound(MyBase.Sound, 0, 0, Guid.Empty, loopForever, 0, 12, parent); + lock (Graphics.AnimationLock) { - mLowerLoop = animBase.Lower.LoopCount; - mUpperLoop = animBase.Upper.LoopCount; - mLowerTimer = Timing.Global.MillisecondsUtc + animBase.Lower.FrameSpeed; - mUpperTimer = Timing.Global.MillisecondsUtc + animBase.Upper.FrameSpeed; - InfiniteLoop = loopForever; - AutoRotate = autoRotate; - mZDimension = zDimension; - mSound = Audio.AddMapSound(MyBase.Sound, 0, 0, Guid.Empty, loopForever, 0, 12, parent); - lock (Graphics.AnimationLock) - { - Graphics.LiveAnimations.Add(this); - } - } - else - { - Dispose(); + Graphics.LiveAnimations.Add(this); } } + else + { + Dispose(); + } + } - public void Draw(bool upper = false, bool alternate = false) + public void Draw(bool upper = false, bool alternate = false) + { + if (Hidden) { - if (Hidden) - { - return; - } + return; + } - if (!upper && alternate != MyBase.Lower.AlternateRenderLayer) - { - return; - } + if (!upper && alternate != MyBase.Lower.AlternateRenderLayer) + { + return; + } - if (upper && alternate != MyBase.Upper.AlternateRenderLayer) - { - return; - } + if (upper && alternate != MyBase.Upper.AlternateRenderLayer) + { + return; + } - var rotationDegrees = 0f; - var dontRotate = upper && MyBase.Upper.DisableRotations || !upper && MyBase.Lower.DisableRotations; + var rotationDegrees = 0f; + var dontRotate = upper && MyBase.Upper.DisableRotations || !upper && MyBase.Lower.DisableRotations; - if (mUseExternalRotation) - { - rotationDegrees = mExternalRotation; - } + if (mUseExternalRotation) + { + rotationDegrees = mExternalRotation; + } - if ((AutoRotate || mRenderDir != Direction.None) && !dontRotate && !mUseExternalRotation) + if ((AutoRotate || mRenderDir != Direction.None) && !dontRotate && !mUseExternalRotation) + { + switch (mRenderDir) { - switch (mRenderDir) - { - case Direction.Up: - rotationDegrees = 0f; + case Direction.Up: + rotationDegrees = 0f; - break; - case Direction.Down: - rotationDegrees = 180f; + break; + case Direction.Down: + rotationDegrees = 180f; - break; - case Direction.Left: - rotationDegrees = 270f; + break; + case Direction.Left: + rotationDegrees = 270f; - break; - case Direction.Right: - rotationDegrees = 90f; + break; + case Direction.Right: + rotationDegrees = 90f; - break; - case Direction.UpLeft: - rotationDegrees = 315f; + break; + case Direction.UpLeft: + rotationDegrees = 315f; - break; - case Direction.UpRight: - rotationDegrees = 45f; + break; + case Direction.UpRight: + rotationDegrees = 45f; - break; - case Direction.DownRight: - rotationDegrees = 135f; + break; + case Direction.DownRight: + rotationDegrees = 135f; - break; - case Direction.DownLeft: - rotationDegrees = 225f; + break; + case Direction.DownLeft: + rotationDegrees = 225f; - break; - } + break; } + } - if (!upper && mShowLower && mZDimension < 1 || !upper && mShowLower && mZDimension > 0) - { - //Draw Lower - var tex = Globals.ContentManager.GetTexture( - Framework.Content.TextureType.Animation, MyBase.Lower.Sprite - ); - - if (tex != null) - { - if (MyBase.Lower.XFrames > 0 && MyBase.Lower.YFrames > 0) - { - var frameWidth = tex.GetWidth() / MyBase.Lower.XFrames; - var frameHeight = tex.GetHeight() / MyBase.Lower.YFrames; - Graphics.DrawGameTexture( - tex, - new FloatRect( - mLowerFrame % MyBase.Lower.XFrames * frameWidth, - (float)Math.Floor((double)mLowerFrame / MyBase.Lower.XFrames) * frameHeight, - frameWidth, frameHeight - ), - new FloatRect( - mRenderX - frameWidth / 2, mRenderY - frameHeight / 2, frameWidth, frameHeight - ), Color.White, null, GameBlendModes.None, null, rotationDegrees - ); - } - } - - var offsetX = MyBase.Lower.Lights[mLowerFrame].OffsetX; - var offsetY = MyBase.Lower.Lights[mLowerFrame].OffsetY; - var offset = RotatePoint( - new Point(offsetX, offsetY), new Point(0, 0), rotationDegrees + 180 - ); - - Graphics.AddLight( - (int)mRenderX - offset.X, (int)mRenderY - offset.Y, MyBase.Lower.Lights[mLowerFrame].Size, - MyBase.Lower.Lights[mLowerFrame].Intensity, MyBase.Lower.Lights[mLowerFrame].Expand, - MyBase.Lower.Lights[mLowerFrame].Color - ); - } + if (!upper && mShowLower && mZDimension < 1 || !upper && mShowLower && mZDimension > 0) + { + //Draw Lower + var tex = Globals.ContentManager.GetTexture( + Framework.Content.TextureType.Animation, MyBase.Lower.Sprite + ); - if (upper && mShowUpper && mZDimension != 0 || upper && mShowUpper && mZDimension == 0) + if (tex != null) { - //Draw Upper - var tex = Globals.ContentManager.GetTexture( - Framework.Content.TextureType.Animation, MyBase.Upper.Sprite - ); - - if (tex != null) + if (MyBase.Lower.XFrames > 0 && MyBase.Lower.YFrames > 0) { - if (MyBase.Upper.XFrames > 0 && MyBase.Upper.YFrames > 0) - { - var frameWidth = tex.GetWidth() / MyBase.Upper.XFrames; - var frameHeight = tex.GetHeight() / MyBase.Upper.YFrames; - - Graphics.DrawGameTexture( - tex, - new FloatRect( - mUpperFrame % MyBase.Upper.XFrames * frameWidth, - (float)Math.Floor((double)mUpperFrame / MyBase.Upper.XFrames) * frameHeight, - frameWidth, frameHeight - ), - new FloatRect( - mRenderX - frameWidth / 2, mRenderY - frameHeight / 2, frameWidth, frameHeight - ), Color.White, null, GameBlendModes.None, null, rotationDegrees - ); - } + var frameWidth = tex.GetWidth() / MyBase.Lower.XFrames; + var frameHeight = tex.GetHeight() / MyBase.Lower.YFrames; + Graphics.DrawGameTexture( + tex, + new FloatRect( + mLowerFrame % MyBase.Lower.XFrames * frameWidth, + (float)Math.Floor((double)mLowerFrame / MyBase.Lower.XFrames) * frameHeight, + frameWidth, frameHeight + ), + new FloatRect( + mRenderX - frameWidth / 2, mRenderY - frameHeight / 2, frameWidth, frameHeight + ), Color.White, null, GameBlendModes.None, null, rotationDegrees + ); } - - var offsetX = MyBase.Upper.Lights[mUpperFrame].OffsetX; - var offsetY = MyBase.Upper.Lights[mUpperFrame].OffsetY; - var offset = RotatePoint( - new Point(offsetX, offsetY), new Point(0, 0), rotationDegrees + 180 - ); - - Graphics.AddLight( - (int)mRenderX - offset.X, (int)mRenderY - offset.Y, MyBase.Upper.Lights[mUpperFrame].Size, - MyBase.Upper.Lights[mUpperFrame].Intensity, MyBase.Upper.Lights[mUpperFrame].Expand, - MyBase.Upper.Lights[mUpperFrame].Color - ); } + + var offsetX = MyBase.Lower.Lights[mLowerFrame].OffsetX; + var offsetY = MyBase.Lower.Lights[mLowerFrame].OffsetY; + var offset = RotatePoint( + new Point(offsetX, offsetY), new Point(0, 0), rotationDegrees + 180 + ); + + Graphics.AddLight( + (int)mRenderX - offset.X, (int)mRenderY - offset.Y, MyBase.Lower.Lights[mLowerFrame].Size, + MyBase.Lower.Lights[mLowerFrame].Intensity, MyBase.Lower.Lights[mLowerFrame].Expand, + MyBase.Lower.Lights[mLowerFrame].Color + ); } - public void EndDraw() + if (upper && mShowUpper && mZDimension != 0 || upper && mShowUpper && mZDimension == 0) { - if (mDisposeNextDraw) + //Draw Upper + var tex = Globals.ContentManager.GetTexture( + Framework.Content.TextureType.Animation, MyBase.Upper.Sprite + ); + + if (tex != null) { - Dispose(); + if (MyBase.Upper.XFrames > 0 && MyBase.Upper.YFrames > 0) + { + var frameWidth = tex.GetWidth() / MyBase.Upper.XFrames; + var frameHeight = tex.GetHeight() / MyBase.Upper.YFrames; + + Graphics.DrawGameTexture( + tex, + new FloatRect( + mUpperFrame % MyBase.Upper.XFrames * frameWidth, + (float)Math.Floor((double)mUpperFrame / MyBase.Upper.XFrames) * frameHeight, + frameWidth, frameHeight + ), + new FloatRect( + mRenderX - frameWidth / 2, mRenderY - frameHeight / 2, frameWidth, frameHeight + ), Color.White, null, GameBlendModes.None, null, rotationDegrees + ); + } } + + var offsetX = MyBase.Upper.Lights[mUpperFrame].OffsetX; + var offsetY = MyBase.Upper.Lights[mUpperFrame].OffsetY; + var offset = RotatePoint( + new Point(offsetX, offsetY), new Point(0, 0), rotationDegrees + 180 + ); + + Graphics.AddLight( + (int)mRenderX - offset.X, (int)mRenderY - offset.Y, MyBase.Upper.Lights[mUpperFrame].Size, + MyBase.Upper.Lights[mUpperFrame].Intensity, MyBase.Upper.Lights[mUpperFrame].Expand, + MyBase.Upper.Lights[mUpperFrame].Color + ); } + } - static Point RotatePoint(Point pointToRotate, Point centerPoint, double angleInDegrees) + public void EndDraw() + { + if (mDisposeNextDraw) { - var angleInRadians = angleInDegrees * (Math.PI / 180); - var cosTheta = Math.Cos(angleInRadians); - var sinTheta = Math.Sin(angleInRadians); - - return new Point { - X = (int)(cosTheta * (pointToRotate.X - centerPoint.X) - - sinTheta * (pointToRotate.Y - centerPoint.Y) + - centerPoint.X), - Y = (int)(sinTheta * (pointToRotate.X - centerPoint.X) + - cosTheta * (pointToRotate.Y - centerPoint.Y) + - centerPoint.Y) - }; + Dispose(); } + } + + static Point RotatePoint(Point pointToRotate, Point centerPoint, double angleInDegrees) + { + var angleInRadians = angleInDegrees * (Math.PI / 180); + var cosTheta = Math.Cos(angleInRadians); + var sinTheta = Math.Sin(angleInRadians); + + return new Point { + X = (int)(cosTheta * (pointToRotate.X - centerPoint.X) - + sinTheta * (pointToRotate.Y - centerPoint.Y) + + centerPoint.X), + Y = (int)(sinTheta * (pointToRotate.X - centerPoint.X) + + cosTheta * (pointToRotate.Y - centerPoint.Y) + + centerPoint.Y) + }; + } + + public void Hide() + { + Hidden = true; + } - public void Hide() + public void Show() + { + Hidden = false; + } + + public bool ParentGone() + { + if (mParent != null && mParent.IsDisposed()) { - Hidden = true; + return true; } - public void Show() + return false; + } + + public void Dispose() + { + if (disposed) { - Hidden = false; + return; } - public bool ParentGone() + lock (Graphics.AnimationLock) { - if (mParent != null && mParent.IsDisposed()) + if (mSound != null) { - return true; + mSound.Loop = false; + if (!MyBase.CompleteSound) + { + mSound.Stop(); + } + + mSound = null; } - return false; + Graphics.LiveAnimations.Remove(this); + disposed = true; } + } - public void Dispose() - { - if (disposed) - { - return; - } - - lock (Graphics.AnimationLock) - { - if (mSound != null) - { - mSound.Loop = false; - if (!MyBase.CompleteSound) - { - mSound.Stop(); - } + public void DisposeNextDraw() + { + mDisposeNextDraw = true; + } - mSound = null; - } + public bool Disposed() + { + return disposed; + } - Graphics.LiveAnimations.Remove(this); - disposed = true; - } + public void SetPosition(float worldX, float worldY, int mapx, int mapy, Guid mapId, Direction dir, int z = 0) + { + mRenderX = worldX; + mRenderY = worldY; + if (mSound != null) + { + mSound.UpdatePosition(mapx, mapy, mapId); } - public void DisposeNextDraw() + if (dir > Direction.None) { - mDisposeNextDraw = true; + mRenderDir = dir; } - public bool Disposed() + mZDimension = z; + } + + public void Update() + { + if (disposed) { - return disposed; + return; } - public void SetPosition(float worldX, float worldY, int mapx, int mapy, Guid mapId, Direction dir, int z = 0) + if (MyBase != null) { - mRenderX = worldX; - mRenderY = worldY; if (mSound != null) { - mSound.UpdatePosition(mapx, mapy, mapId); + mSound.Update(); } - if (dir > Direction.None) + //Calculate Frames + var elapsedTime = Timing.Global.MillisecondsUtc - mStartTime; + + //Lower + if (MyBase.Lower.FrameCount > 0 && MyBase.Lower.FrameSpeed > 0) { - mRenderDir = dir; + var realFrameCount = Math.Min(MyBase.Lower.FrameCount, MyBase.Lower.XFrames * MyBase.Lower.YFrames); + var lowerFrame = (int)Math.Floor(elapsedTime / (float)MyBase.Lower.FrameSpeed); + var lowerLoops = (int)Math.Floor(lowerFrame / (float)realFrameCount); + if (lowerLoops > mLowerLoop && !InfiniteLoop) + { + mShowLower = false; + } + else + { + mLowerFrame = lowerFrame - lowerLoops * realFrameCount; + } } - mZDimension = z; - } + //Upper + if (MyBase.Upper.FrameCount > 0 && MyBase.Upper.FrameSpeed > 0) + { + var realFrameCount = Math.Min(MyBase.Upper.FrameCount, MyBase.Upper.XFrames * MyBase.Upper.YFrames); + var upperFrame = (int)Math.Floor(elapsedTime / (float)MyBase.Upper.FrameSpeed); + var upperLoops = (int)Math.Floor(upperFrame / (float)realFrameCount); + if (upperLoops > mUpperLoop && !InfiniteLoop) + { + mShowUpper = false; + } + else + { + mUpperFrame = upperFrame - upperLoops * realFrameCount; + } + } - public void Update() - { - if (disposed) + if (!mShowLower && !mShowUpper) { - return; + Dispose(); } + } + } - if (MyBase != null) + public Point CalculateAnimationSize() + { + var size = new Point(0, 0); + + var tex = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Animation, MyBase.Lower.Sprite); + if (tex != null) + { + if (MyBase.Lower.XFrames > 0 && MyBase.Lower.YFrames > 0) { - if (mSound != null) + var frameWidth = tex.GetWidth() / MyBase.Lower.XFrames; + var frameHeight = tex.GetHeight() / MyBase.Lower.YFrames; + if (frameWidth > size.X) { - mSound.Update(); + size.X = frameWidth; } - //Calculate Frames - var elapsedTime = Timing.Global.MillisecondsUtc - mStartTime; - - //Lower - if (MyBase.Lower.FrameCount > 0 && MyBase.Lower.FrameSpeed > 0) + if (frameHeight > size.Y) { - var realFrameCount = Math.Min(MyBase.Lower.FrameCount, MyBase.Lower.XFrames * MyBase.Lower.YFrames); - var lowerFrame = (int)Math.Floor(elapsedTime / (float)MyBase.Lower.FrameSpeed); - var lowerLoops = (int)Math.Floor(lowerFrame / (float)realFrameCount); - if (lowerLoops > mLowerLoop && !InfiniteLoop) - { - mShowLower = false; - } - else - { - mLowerFrame = lowerFrame - lowerLoops * realFrameCount; - } + size.Y = frameHeight; } + } + } - //Upper - if (MyBase.Upper.FrameCount > 0 && MyBase.Upper.FrameSpeed > 0) + tex = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Animation, MyBase.Upper.Sprite); + if (tex != null) + { + if (MyBase.Upper.XFrames > 0 && MyBase.Upper.YFrames > 0) + { + var frameWidth = tex.GetWidth() / MyBase.Upper.XFrames; + var frameHeight = tex.GetHeight() / MyBase.Upper.YFrames; + if (frameWidth > size.X) { - var realFrameCount = Math.Min(MyBase.Upper.FrameCount, MyBase.Upper.XFrames * MyBase.Upper.YFrames); - var upperFrame = (int)Math.Floor(elapsedTime / (float)MyBase.Upper.FrameSpeed); - var upperLoops = (int)Math.Floor(upperFrame / (float)realFrameCount); - if (upperLoops > mUpperLoop && !InfiniteLoop) - { - mShowUpper = false; - } - else - { - mUpperFrame = upperFrame - upperLoops * realFrameCount; - } + size.X = frameWidth; } - if (!mShowLower && !mShowUpper) + if (frameHeight > size.Y) { - Dispose(); + size.Y = frameHeight; } } } - public Point CalculateAnimationSize() + foreach (var light in MyBase.Lower.Lights) { - var size = new Point(0, 0); - - var tex = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Animation, MyBase.Lower.Sprite); - if (tex != null) + if (light != null) { - if (MyBase.Lower.XFrames > 0 && MyBase.Lower.YFrames > 0) + if (light.Size + Math.Abs(light.OffsetX) > size.X) { - var frameWidth = tex.GetWidth() / MyBase.Lower.XFrames; - var frameHeight = tex.GetHeight() / MyBase.Lower.YFrames; - if (frameWidth > size.X) - { - size.X = frameWidth; - } - - if (frameHeight > size.Y) - { - size.Y = frameHeight; - } + size.X = light.Size + light.OffsetX; } - } - tex = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Animation, MyBase.Upper.Sprite); - if (tex != null) - { - if (MyBase.Upper.XFrames > 0 && MyBase.Upper.YFrames > 0) + if (light.Size + Math.Abs(light.OffsetY) > size.Y) { - var frameWidth = tex.GetWidth() / MyBase.Upper.XFrames; - var frameHeight = tex.GetHeight() / MyBase.Upper.YFrames; - if (frameWidth > size.X) - { - size.X = frameWidth; - } - - if (frameHeight > size.Y) - { - size.Y = frameHeight; - } + size.Y = light.Size + light.OffsetY; } } + } - foreach (var light in MyBase.Lower.Lights) + foreach (var light in MyBase.Upper.Lights) + { + if (light != null) { - if (light != null) + if (light.Size + Math.Abs(light.OffsetX) > size.X) { - if (light.Size + Math.Abs(light.OffsetX) > size.X) - { - size.X = light.Size + light.OffsetX; - } - - if (light.Size + Math.Abs(light.OffsetY) > size.Y) - { - size.Y = light.Size + light.OffsetY; - } + size.X = light.Size + light.OffsetX; } - } - foreach (var light in MyBase.Upper.Lights) - { - if (light != null) + if (light.Size + Math.Abs(light.OffsetY) > size.Y) { - if (light.Size + Math.Abs(light.OffsetX) > size.X) - { - size.X = light.Size + light.OffsetX; - } - - if (light.Size + Math.Abs(light.OffsetY) > size.Y) - { - size.Y = light.Size + light.OffsetY; - } + size.Y = light.Size + light.OffsetY; } } - - return size; } - public void SetDir(Direction dir) - { - mRenderDir = dir; - } + return size; + } - public void SetRotation(float angleInDegrees) - { - mUseExternalRotation = true; - mExternalRotation = angleInDegrees; - } + public void SetDir(Direction dir) + { + mRenderDir = dir; + } - public void SetRotation(bool toggle) - { - mUseExternalRotation = toggle; - } + public void SetRotation(float angleInDegrees) + { + mUseExternalRotation = true; + mExternalRotation = angleInDegrees; } + public void SetRotation(bool toggle) + { + mUseExternalRotation = toggle; + } } diff --git a/Intersect.Client/Entities/ChatBubble.cs b/Intersect.Client/Entities/ChatBubble.cs index ddc08e5e8a..ecb223c350 100644 --- a/Intersect.Client/Entities/ChatBubble.cs +++ b/Intersect.Client/Entities/ChatBubble.cs @@ -5,198 +5,196 @@ using Intersect.Client.General; using Intersect.Utilities; -namespace Intersect.Client.Entities -{ +namespace Intersect.Client.Entities; - public partial class ChatBubble - { - private GameTexture mBubbleTex; +public partial class ChatBubble +{ - private Entity mOwner; + private GameTexture mBubbleTex; - private Color mRenderColor; + private Entity mOwner; - private long mRenderTimer; + private Color mRenderColor; - private string mSourceText; + private long mRenderTimer; - private Point[,] mTexSections; + private string mSourceText; - private string[] mText; + private Point[,] mTexSections; - private Rectangle mTextBounds; + private string[] mText; - private Rectangle mTextureBounds; + private Rectangle mTextBounds; - public ChatBubble(Entity owner, string text) + private Rectangle mTextureBounds; + + public ChatBubble(Entity owner, string text) + { + if (string.IsNullOrEmpty(text)) { - if (string.IsNullOrEmpty(text)) - { - return; - } + return; + } + + mOwner = owner; + mSourceText = text; + mRenderTimer = Timing.Global.MillisecondsUtc + 5000; + mBubbleTex = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Misc, "chatbubble.png"); + } - mOwner = owner; - mSourceText = text; - mRenderTimer = Timing.Global.MillisecondsUtc + 5000; - mBubbleTex = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Misc, "chatbubble.png"); + public bool Update() + { + if (mRenderTimer < Timing.Global.MillisecondsUtc) + { + return false; } - public bool Update() + return true; + } + + public float Draw(float yoffset = 0f) + { + if (mText == null && mSourceText.Trim().Length > 0) { - if (mRenderTimer < Timing.Global.MillisecondsUtc) - { - return false; - } + mText = Interface.Interface.WrapText(mSourceText, 200, Graphics.ChatBubbleFont); + } - return true; + if (mText == null) + { + return 0f; } - public float Draw(float yoffset = 0f) + var x = (int)Math.Ceiling(mOwner.Origin.X); + var y = (int) Math.Ceiling(mOwner.GetLabelLocation(LabelType.ChatBubble)); + + if (mTextureBounds.Width == 0) { - if (mText == null && mSourceText.Trim().Length > 0) + //Gotta Calculate Bounds + for (var i = (mText?.Length ?? 0) - 1; i > -1; i--) + { + var textSize = Graphics.Renderer.MeasureText(mText[i], Graphics.ChatBubbleFont, 1); + if (textSize.X > mTextureBounds.Width) + { + mTextureBounds.Width = (int) textSize.X + 16; + } + + mTextureBounds.Height += (int) textSize.Y + 2; + if (textSize.X > mTextBounds.Width) + { + mTextBounds.Width = (int) textSize.X; + } + + mTextBounds.Height += (int) textSize.Y + 2; + } + + mTextureBounds.Height += 16; + if (mTextureBounds.Width < 48) { - mText = Interface.Interface.WrapText(mSourceText, 200, Graphics.ChatBubbleFont); + mTextureBounds.Width = 48; } - if (mText == null) + if (mTextureBounds.Height < 32) { - return 0f; + mTextureBounds.Height = 32; } - var x = (int)Math.Ceiling(mOwner.Origin.X); - var y = (int) Math.Ceiling(mOwner.GetLabelLocation(LabelType.ChatBubble)); + mTextureBounds.Width = (int) (Math.Round(mTextureBounds.Width / 8.0) * 8.0); + mTextureBounds.Height = (int) (Math.Round(mTextureBounds.Height / 8.0) * 8.0); + if (mTextureBounds.Width / 8 % 2 != 0) + { + mTextureBounds.Width += 8; + } - if (mTextureBounds.Width == 0) + mTexSections = new Point[mTextureBounds.Width / 8, mTextureBounds.Height / 8]; + for (var x1 = 0; x1 < mTextureBounds.Width / 8; x1++) { - //Gotta Calculate Bounds - for (var i = (mText?.Length ?? 0) - 1; i > -1; i--) + for (var y1 = 0; y1 < mTextureBounds.Height / 8; y1++) { - var textSize = Graphics.Renderer.MeasureText(mText[i], Graphics.ChatBubbleFont, 1); - if (textSize.X > mTextureBounds.Width) + if (x1 == 0) { - mTextureBounds.Width = (int) textSize.X + 16; + mTexSections[x1, y1].X = 0; } - - mTextureBounds.Height += (int) textSize.Y + 2; - if (textSize.X > mTextBounds.Width) + else if (x1 == 1) { - mTextBounds.Width = (int) textSize.X; + mTexSections[x1, y1].X = 1; } - - mTextBounds.Height += (int) textSize.Y + 2; - } - - mTextureBounds.Height += 16; - if (mTextureBounds.Width < 48) - { - mTextureBounds.Width = 48; - } - - if (mTextureBounds.Height < 32) - { - mTextureBounds.Height = 32; - } - - mTextureBounds.Width = (int) (Math.Round(mTextureBounds.Width / 8.0) * 8.0); - mTextureBounds.Height = (int) (Math.Round(mTextureBounds.Height / 8.0) * 8.0); - if (mTextureBounds.Width / 8 % 2 != 0) - { - mTextureBounds.Width += 8; - } - - mTexSections = new Point[mTextureBounds.Width / 8, mTextureBounds.Height / 8]; - for (var x1 = 0; x1 < mTextureBounds.Width / 8; x1++) - { - for (var y1 = 0; y1 < mTextureBounds.Height / 8; y1++) + else if (x1 == mTextureBounds.Width / 16 - 1) { - if (x1 == 0) - { - mTexSections[x1, y1].X = 0; - } - else if (x1 == 1) - { - mTexSections[x1, y1].X = 1; - } - else if (x1 == mTextureBounds.Width / 16 - 1) - { - mTexSections[x1, y1].X = 3; - } - else if (x1 == mTextureBounds.Width / 16) - { - mTexSections[x1, y1].X = 4; - } - else if (x1 == mTextureBounds.Width / 8 - 1) - { - mTexSections[x1, y1].X = 7; - } - else if (x1 == mTextureBounds.Width / 8 - 2) - { - mTexSections[x1, y1].X = 6; - } - else - { - mTexSections[x1, y1].X = 2; - } - - if (y1 == 0) - { - mTexSections[x1, y1].Y = 0; - } - else if (y1 == 1) - { - mTexSections[x1, y1].Y = 1; - } - else if (y1 == mTextureBounds.Height / 8 - 1) - { - mTexSections[x1, y1].Y = 3; - } - else if (y1 == mTextureBounds.Height / 8 - 2) - { - mTexSections[x1, y1].Y = 2; - } - else - { - mTexSections[x1, y1].Y = 1; - } + mTexSections[x1, y1].X = 3; + } + else if (x1 == mTextureBounds.Width / 16) + { + mTexSections[x1, y1].X = 4; + } + else if (x1 == mTextureBounds.Width / 8 - 1) + { + mTexSections[x1, y1].X = 7; + } + else if (x1 == mTextureBounds.Width / 8 - 2) + { + mTexSections[x1, y1].X = 6; + } + else + { + mTexSections[x1, y1].X = 2; } - } - } - if (mBubbleTex != null) - { - //Draw Background if available - //Draw Top Left - for (var x1 = 0; x1 < mTextureBounds.Width / 8; x1++) - { - for (var y1 = 0; y1 < mTextureBounds.Height / 8; y1++) + if (y1 == 0) + { + mTexSections[x1, y1].Y = 0; + } + else if (y1 == 1) + { + mTexSections[x1, y1].Y = 1; + } + else if (y1 == mTextureBounds.Height / 8 - 1) + { + mTexSections[x1, y1].Y = 3; + } + else if (y1 == mTextureBounds.Height / 8 - 2) + { + mTexSections[x1, y1].Y = 2; + } + else { - Graphics.Renderer.DrawTexture( - mBubbleTex, mTexSections[x1, y1].X * 8, mTexSections[x1, y1].Y * 8, 8, 8, - x - mTextureBounds.Width / 2 + x1 * 8, y - mTextureBounds.Height - yoffset + y1 * 8, 8, 8, - Color.White - ); + mTexSections[x1, y1].Y = 1; } } + } + } - for (var i = mText.Length - 1; i > -1; i--) + if (mBubbleTex != null) + { + //Draw Background if available + //Draw Top Left + for (var x1 = 0; x1 < mTextureBounds.Width / 8; x1++) + { + for (var y1 = 0; y1 < mTextureBounds.Height / 8; y1++) { - var textSize = Graphics.Renderer.MeasureText(mText[i], Graphics.ChatBubbleFont, 1); - Graphics.Renderer.DrawString( - mText[i], Graphics.ChatBubbleFont, - (int) (x - mTextureBounds.Width / 2 + (mTextureBounds.Width - textSize.X) / 2f), - (int) (y - mTextureBounds.Height - yoffset + 8 + i * 16), 1, - Color.FromArgb(CustomColors.Chat.ChatBubbleText.ToArgb()), true, null, - Color.FromArgb(CustomColors.Chat.ChatBubbleTextOutline.ToArgb()) + Graphics.Renderer.DrawTexture( + mBubbleTex, mTexSections[x1, y1].X * 8, mTexSections[x1, y1].Y * 8, 8, 8, + x - mTextureBounds.Width / 2 + x1 * 8, y - mTextureBounds.Height - yoffset + y1 * 8, 8, 8, + Color.White ); } } - yoffset += mTextureBounds.Height; - - return yoffset; + for (var i = mText.Length - 1; i > -1; i--) + { + var textSize = Graphics.Renderer.MeasureText(mText[i], Graphics.ChatBubbleFont, 1); + Graphics.Renderer.DrawString( + mText[i], Graphics.ChatBubbleFont, + (int) (x - mTextureBounds.Width / 2 + (mTextureBounds.Width - textSize.X) / 2f), + (int) (y - mTextureBounds.Height - yoffset + 8 + i * 16), 1, + Color.FromArgb(CustomColors.Chat.ChatBubbleText.ToArgb()), true, null, + Color.FromArgb(CustomColors.Chat.ChatBubbleTextOutline.ToArgb()) + ); + } } + yoffset += mTextureBounds.Height; + + return yoffset; } } diff --git a/Intersect.Client/Entities/Critter.cs b/Intersect.Client/Entities/Critter.cs index f52bc444de..c9ebf7eed9 100644 --- a/Intersect.Client/Entities/Critter.cs +++ b/Intersect.Client/Entities/Critter.cs @@ -8,286 +8,285 @@ using Intersect.GameObjects.Maps; using Intersect.Utilities; -namespace Intersect.Client.Entities +namespace Intersect.Client.Entities; + +public partial class Critter : Entity { - public partial class Critter : Entity + private MapCritterAttribute mAttribute; + private long mLastMove = -1; + + public Critter(MapInstance map, byte x, byte y, MapCritterAttribute att) : base(Guid.NewGuid(), null, EntityType.GlobalEntity) { - private MapCritterAttribute mAttribute; - private long mLastMove = -1; + mAttribute = att; - public Critter(MapInstance map, byte x, byte y, MapCritterAttribute att) : base(Guid.NewGuid(), null, EntityType.GlobalEntity) + //setup Sprite & Animation + Sprite = att?.Sprite; + var anim = AnimationBase.Get(att.AnimationId); + if (anim != null) { - mAttribute = att; - - //setup Sprite & Animation - Sprite = att?.Sprite; - var anim = AnimationBase.Get(att.AnimationId); - if (anim != null) - { - var animInstance = new Animation(anim, true); - Animations.Add(animInstance); - } + var animInstance = new Animation(anim, true); + Animations.Add(animInstance); + } - //Define Location - MapId = map?.Id ?? default; - X = x; - Y = y; + //Define Location + MapId = map?.Id ?? default; + X = x; + Y = y; - //Determine Direction - if (mAttribute.Direction == 0) - { - Dir = Randomization.NextDirection(); - } - else - { - Dir = (Direction)(mAttribute.Direction - 1); - } - - //Block Players? - Passable = !att.BlockPlayers; + //Determine Direction + if (mAttribute.Direction == 0) + { + Dir = Randomization.NextDirection(); + } + else + { + Dir = (Direction)(mAttribute.Direction - 1); } - public override bool Update() + //Block Players? + Passable = !att.BlockPlayers; + } + + public override bool Update() + { + if (base.Update()) { - if (base.Update()) + if (mLastMove < Timing.Global.MillisecondsUtc) { - if (mLastMove < Timing.Global.MillisecondsUtc) + switch (mAttribute.Movement) { - switch (mAttribute.Movement) - { - case 0: //Move Randomly - MoveRandomly(); - break; - case 1: //Turn? - Dir = Randomization.NextDirection(); - break; - - } + case 0: //Move Randomly + MoveRandomly(); + break; + case 1: //Turn? + Dir = Randomization.NextDirection(); + break; - mLastMove = Timing.Global.MillisecondsUtc + mAttribute.Frequency + Globals.Random.Next((int)(mAttribute.Frequency * .5f)); } - return true; + + mLastMove = Timing.Global.MillisecondsUtc + mAttribute.Frequency + Globals.Random.Next((int)(mAttribute.Frequency * .5f)); } - return false; + return true; } + return false; + } + + private void MoveRandomly() + { + MoveDir = Randomization.NextDirection(); + var tmpX = (sbyte)X; + var tmpY = (sbyte)Y; + IEntity blockedBy = null; - private void MoveRandomly() + if (IsMoving || MoveTimer >= Timing.Global.MillisecondsUtc) { - MoveDir = Randomization.NextDirection(); - var tmpX = (sbyte)X; - var tmpY = (sbyte)Y; - IEntity blockedBy = null; + return; + } - if (IsMoving || MoveTimer >= Timing.Global.MillisecondsUtc) - { - return; - } + var deltaX = 0; + var deltaY = 0; - var deltaX = 0; - var deltaY = 0; + switch (MoveDir) + { + case Direction.Up: + deltaX = 0; + deltaY = -1; + break; + + case Direction.Down: + deltaX = 0; + deltaY = 1; + break; + + case Direction.Left: + deltaX = -1; + deltaY = 0; + break; + + case Direction.Right: + deltaX = 1; + deltaY = 0; + break; + + case Direction.UpLeft: + deltaX = -1; + deltaY = -1; + break; + + case Direction.UpRight: + deltaX = 1; + deltaY = -1; + break; + + case Direction.DownLeft: + deltaX = -1; + deltaY = 1; + break; + + case Direction.DownRight: + deltaX = 1; + deltaY = 1; + break; + } - switch (MoveDir) + if (deltaX != 0 || deltaY != 0) + { + var newX = tmpX + deltaX; + var newY = tmpY + deltaY; + var isBlocked = -1 == + IsTileBlocked( + new Point(newX, newY), + Z, + MapId, + ref blockedBy, + true, + true, + mAttribute.IgnoreNpcAvoids + ); + var playerOnTile = PlayerOnTile(MapId, newX, newY); + + if (isBlocked && newX >= 0 && newX < Options.MapWidth && newY >= 0 && newY < Options.MapHeight && + (!mAttribute.BlockPlayers || !playerOnTile)) { - case Direction.Up: - deltaX = 0; - deltaY = -1; - break; - - case Direction.Down: - deltaX = 0; - deltaY = 1; - break; - - case Direction.Left: - deltaX = -1; - deltaY = 0; - break; - - case Direction.Right: - deltaX = 1; - deltaY = 0; - break; - - case Direction.UpLeft: - deltaX = -1; - deltaY = -1; - break; - - case Direction.UpRight: - deltaX = 1; - deltaY = -1; - break; - - case Direction.DownLeft: - deltaX = -1; - deltaY = 1; - break; - - case Direction.DownRight: - deltaX = 1; - deltaY = 1; - break; - } + tmpX += (sbyte)deltaX; + tmpY += (sbyte)deltaY; + IsMoving = true; + Dir = MoveDir; - if (deltaX != 0 || deltaY != 0) - { - var newX = tmpX + deltaX; - var newY = tmpY + deltaY; - var isBlocked = -1 == - IsTileBlocked( - new Point(newX, newY), - Z, - MapId, - ref blockedBy, - true, - true, - mAttribute.IgnoreNpcAvoids - ); - var playerOnTile = PlayerOnTile(MapId, newX, newY); - - if (isBlocked && newX >= 0 && newX < Options.MapWidth && newY >= 0 && newY < Options.MapHeight && - (!mAttribute.BlockPlayers || !playerOnTile)) + if (deltaX == 0) { - tmpX += (sbyte)deltaX; - tmpY += (sbyte)deltaY; - IsMoving = true; - Dir = MoveDir; - - if (deltaX == 0) - { - OffsetX = 0; - } - else - { - OffsetX = deltaX > 0 ? -Options.TileWidth : Options.TileWidth; - } + OffsetX = 0; + } + else + { + OffsetX = deltaX > 0 ? -Options.TileWidth : Options.TileWidth; + } - if (deltaY == 0) - { - OffsetY = 0; - } - else - { - OffsetY = deltaY > 0 ? -Options.TileHeight : Options.TileHeight; - } + if (deltaY == 0) + { + OffsetY = 0; + } + else + { + OffsetY = deltaY > 0 ? -Options.TileHeight : Options.TileHeight; } } + } - if (IsMoving) - { - X = (byte)tmpX; - Y = (byte)tmpY; - MoveTimer = Timing.Global.MillisecondsUtc + (long)GetMovementTime(); - } - else if (MoveDir != Dir) - { - Dir = MoveDir; - } + if (IsMoving) + { + X = (byte)tmpX; + Y = (byte)tmpY; + MoveTimer = Timing.Global.MillisecondsUtc + (long)GetMovementTime(); } + else if (MoveDir != Dir) + { + Dir = MoveDir; + } + } - public bool PlayerOnTile(Guid mapId, int x, int y) + public bool PlayerOnTile(Guid mapId, int x, int y) + { + foreach (var en in Globals.Entities) { - foreach (var en in Globals.Entities) + if (en.Value == null) { - if (en.Value == null) - { - continue; - } + continue; + } - if (en.Value.MapId == mapId && - en.Value.X == x && - en.Value.Y == y) + if (en.Value.MapId == mapId && + en.Value.X == x && + en.Value.Y == y) + { + if (en.Value is Player) { - if (en.Value is Player) - { - return true; - } + return true; } } - return false; } + return false; + } - public override HashSet DetermineRenderOrder(HashSet renderList, IMapInstance map) + public override HashSet DetermineRenderOrder(HashSet renderList, IMapInstance map) + { + if (mAttribute.Layer == 1) { - if (mAttribute.Layer == 1) - { - return base.DetermineRenderOrder(renderList, map); - } + return base.DetermineRenderOrder(renderList, map); + } - renderList?.Remove(this); - if (map == null || Globals.Me == null || Globals.Me.MapInstance == null) - { - return null; - } + renderList?.Remove(this); + if (map == null || Globals.Me == null || Globals.Me.MapInstance == null) + { + return null; + } - var gridX = Globals.Me.MapInstance.GridX; - var gridY = Globals.Me.MapInstance.GridY; - for (var x = gridX - 1; x <= gridX + 1; x++) + var gridX = Globals.Me.MapInstance.GridX; + var gridY = Globals.Me.MapInstance.GridY; + for (var x = gridX - 1; x <= gridX + 1; x++) + { + for (var y = gridY - 1; y <= gridY + 1; y++) { - for (var y = gridY - 1; y <= gridY + 1; y++) + if (x >= 0 && + x < Globals.MapGridWidth && + y >= 0 && + y < Globals.MapGridHeight && + Globals.MapGrid[x, y] != Guid.Empty) { - if (x >= 0 && - x < Globals.MapGridWidth && - y >= 0 && - y < Globals.MapGridHeight && - Globals.MapGrid[x, y] != Guid.Empty) + if (Globals.MapGrid[x, y] == MapId) { - if (Globals.MapGrid[x, y] == MapId) + if (mAttribute.Layer == 0) + { + y--; + } + + if (mAttribute.Layer == 2) + { + y++; + } + + var priority = mRenderPriority; + if (Z != 0) + { + priority += 3; + } + + HashSet renderSet = null; + + if (y == gridY - 2) + { + renderSet = Graphics.RenderingEntities[priority, Y]; + } + else if (y == gridY - 1) + { + renderSet = Graphics.RenderingEntities[priority, Options.MapHeight + Y]; + } + else if (y == gridY) { - if (mAttribute.Layer == 0) - { - y--; - } - - if (mAttribute.Layer == 2) - { - y++; - } - - var priority = mRenderPriority; - if (Z != 0) - { - priority += 3; - } - - HashSet renderSet = null; - - if (y == gridY - 2) - { - renderSet = Graphics.RenderingEntities[priority, Y]; - } - else if (y == gridY - 1) - { - renderSet = Graphics.RenderingEntities[priority, Options.MapHeight + Y]; - } - else if (y == gridY) - { - renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * 2 + Y]; - } - else if (y == gridY + 1) - { - renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * 3 + Y]; - } - else if (y == gridY + 2) - { - renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * 4 + Y]; - } - - renderSet?.Add(this); - renderList = renderSet; - - return renderList; + renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * 2 + Y]; } + else if (y == gridY + 1) + { + renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * 3 + Y]; + } + else if (y == gridY + 2) + { + renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * 4 + Y]; + } + + renderSet?.Add(this); + renderList = renderSet; + + return renderList; } } } - - return renderList; } - public override float GetMovementTime() - { - return mAttribute.Speed; - } + return renderList; + } + + public override float GetMovementTime() + { + return mAttribute.Speed; } } diff --git a/Intersect.Client/Entities/Dash.cs b/Intersect.Client/Entities/Dash.cs index 4e8322a4fd..407e309e84 100644 --- a/Intersect.Client/Entities/Dash.cs +++ b/Intersect.Client/Entities/Dash.cs @@ -3,108 +3,106 @@ using Intersect.Enums; using Intersect.Utilities; -namespace Intersect.Client.Entities +namespace Intersect.Client.Entities; + + +public partial class Dash : IDash { - public partial class Dash : IDash - { + private Direction mChangeDirection = Direction.None; - private Direction mChangeDirection = Direction.None; + private int mDashTime; - private int mDashTime; + private Guid mEndMapId; - private Guid mEndMapId; + private byte mEndX; - private byte mEndX; + private float mEndXCoord; - private float mEndXCoord; + private byte mEndY; - private byte mEndY; + private float mEndYCoord; - private float mEndYCoord; + private long mStartTime; - private long mStartTime; + private float mStartXCoord; - private float mStartXCoord; + private float mStartYCoord; - private float mStartYCoord; + public float OffsetX => GetXOffset(); - public float OffsetX => GetXOffset(); + public float OffsetY => GetYOffset(); - public float OffsetY => GetYOffset(); + public Dash(Entity en, Guid endMapId, byte endX, byte endY, int dashTime, Direction changeDirection = Direction.None) + { + mChangeDirection = changeDirection; + mEndMapId = endMapId; + mEndX = endX; + mEndY = endY; + mDashTime = dashTime; + } - public Dash(Entity en, Guid endMapId, byte endX, byte endY, int dashTime, Direction changeDirection = Direction.None) + public void Start(Entity en) + { + if (MapInstance.Get(en.MapId) == null || + MapInstance.Get(mEndMapId) == null || + mEndMapId == en.MapId && mEndX == en.X && mEndY == en.Y) { - mChangeDirection = changeDirection; - mEndMapId = endMapId; - mEndX = endX; - mEndY = endY; - mDashTime = dashTime; + en.Dashing = null; } - - public void Start(Entity en) + else { - if (MapInstance.Get(en.MapId) == null || - MapInstance.Get(mEndMapId) == null || - mEndMapId == en.MapId && mEndX == en.X && mEndY == en.Y) + var startMap = MapInstance.Get(en.MapId); + var endMap = MapInstance.Get(mEndMapId); + mStartTime = Timing.Global.Milliseconds; + mStartXCoord = en.OffsetX; + mStartYCoord = en.OffsetY; + mEndXCoord = endMap.GetX() + mEndX * Options.TileWidth - (startMap.GetX() + en.X * Options.TileWidth); + mEndYCoord = endMap.GetY() + mEndY * Options.TileHeight - (startMap.GetY() + en.Y * Options.TileHeight); + if (mChangeDirection > Direction.None) { - en.Dashing = null; - } - else - { - var startMap = MapInstance.Get(en.MapId); - var endMap = MapInstance.Get(mEndMapId); - mStartTime = Timing.Global.Milliseconds; - mStartXCoord = en.OffsetX; - mStartYCoord = en.OffsetY; - mEndXCoord = endMap.GetX() + mEndX * Options.TileWidth - (startMap.GetX() + en.X * Options.TileWidth); - mEndYCoord = endMap.GetY() + mEndY * Options.TileHeight - (startMap.GetY() + en.Y * Options.TileHeight); - if (mChangeDirection > Direction.None) - { - en.Dir = mChangeDirection; - } + en.Dir = mChangeDirection; } } + } - public float GetXOffset() + public float GetXOffset() + { + if (Timing.Global.Milliseconds > mStartTime + mDashTime) { - if (Timing.Global.Milliseconds > mStartTime + mDashTime) - { - return mEndXCoord; - } - else - { - return (mEndXCoord - mStartXCoord) * ((Timing.Global.Milliseconds - mStartTime) / (float)mDashTime); - } + return mEndXCoord; } - - public float GetYOffset() + else { - if (Timing.Global.Milliseconds > mStartTime + mDashTime) - { - return mEndYCoord; - } - else - { - return (mEndYCoord - mStartYCoord) * ((Timing.Global.Milliseconds - mStartTime) / (float)mDashTime); - } + return (mEndXCoord - mStartXCoord) * ((Timing.Global.Milliseconds - mStartTime) / (float)mDashTime); } + } - public bool Update(Entity en) + public float GetYOffset() + { + if (Timing.Global.Milliseconds > mStartTime + mDashTime) { - if (Timing.Global.Milliseconds > mStartTime + mDashTime) - { - en.Dashing = null; - en.OffsetX = 0; - en.OffsetY = 0; - en.MapId = mEndMapId; - en.X = mEndX; - en.Y = mEndY; - } + return mEndYCoord; + } + else + { + return (mEndYCoord - mStartYCoord) * ((Timing.Global.Milliseconds - mStartTime) / (float)mDashTime); + } + } - return en.Dashing != null; + public bool Update(Entity en) + { + if (Timing.Global.Milliseconds > mStartTime + mDashTime) + { + en.Dashing = null; + en.OffsetX = 0; + en.OffsetY = 0; + en.MapId = mEndMapId; + en.X = mEndX; + en.Y = mEndY; } + return en.Dashing != null; } } diff --git a/Intersect.Client/Entities/Entity.cs b/Intersect.Client/Entities/Entity.cs index 011bb2d3ce..5bf4ca3540 100644 --- a/Intersect.Client/Entities/Entity.cs +++ b/Intersect.Client/Entities/Entity.cs @@ -19,799 +19,789 @@ using Intersect.Utilities; using MapAttribute = Intersect.Enums.MapAttribute; -namespace Intersect.Client.Entities +namespace Intersect.Client.Entities; + +public partial class Entity : IEntity { - public partial class Entity : IEntity - { - public int AnimationFrame { get; set; } + public int AnimationFrame { get; set; } - //Entity Animations - public List Animations { get; set; } = new List(); + //Entity Animations + public List Animations { get; set; } = new List(); - //Animation Timer (for animated sprites) - public long AnimationTimer { get; set; } + //Animation Timer (for animated sprites) + public long AnimationTimer { get; set; } - //Combat - public long AttackTimer { get; set; } = 0; + //Combat + public long AttackTimer { get; set; } = 0; - public int AttackTime { get; set; } = -1; + public int AttackTime { get; set; } = -1; - public long CastTime { get; set; } = 0; + public long CastTime { get; set; } = 0; - //Combat Status - public bool IsAttacking => AttackTimer > Timing.Global.Milliseconds; + //Combat Status + public bool IsAttacking => AttackTimer > Timing.Global.Milliseconds; - public bool IsBlocking { get; set; } = false; + public bool IsBlocking { get; set; } = false; - public bool IsCasting => CastTime > Timing.Global.Milliseconds; + public bool IsCasting => CastTime > Timing.Global.Milliseconds; - public bool IsTurnAroundWhileCastingDisabled => !Options.Instance.CombatOpts.EnableTurnAroundWhileCasting && IsCasting; + public bool IsTurnAroundWhileCastingDisabled => !Options.Instance.CombatOpts.EnableTurnAroundWhileCasting && IsCasting; - public bool IsDashing => Dashing != null; + public bool IsDashing => Dashing != null; - //Dashing instance - public Dash Dashing { get; set; } + //Dashing instance + public Dash Dashing { get; set; } - public IDash CurrentDash => Dashing as IDash; + public IDash CurrentDash => Dashing as IDash; - public Queue DashQueue { get; set; } = new Queue(); + public Queue DashQueue { get; set; } = new Queue(); - public long DashTimer { get; set; } + public long DashTimer { get; set; } - public float elapsedtime { get; set; } //to be removed + public float elapsedtime { get; set; } //to be removed - private Guid[] _equipment = new Guid[Options.EquipmentSlots.Count]; + private Guid[] _equipment = new Guid[Options.EquipmentSlots.Count]; - public Guid[] Equipment + public Guid[] Equipment + { + get => _equipment; + set { - get => _equipment; - set + if (_equipment == value) { - if (_equipment == value) - { - return; - } - - _equipment = value; - LoadAnimationTexture(string.IsNullOrWhiteSpace(TransformedSprite) ? Sprite : TransformedSprite, SpriteAnimations.Weapon); + return; } + + _equipment = value; + LoadAnimationTexture(string.IsNullOrWhiteSpace(TransformedSprite) ? Sprite : TransformedSprite, SpriteAnimations.Weapon); } + } - IReadOnlyList IEntity.EquipmentSlots => MyEquipment.ToList(); + IReadOnlyList IEntity.EquipmentSlots => MyEquipment.ToList(); - public Animation[] EquipmentAnimations { get; set; } = new Animation[Options.EquipmentSlots.Count]; + public Animation[] EquipmentAnimations { get; set; } = new Animation[Options.EquipmentSlots.Count]; - //Extras - public string Face { get; set; } = ""; + //Extras + public string Face { get; set; } = ""; - public Label FooterLabel { get; set; } + public Label FooterLabel { get; set; } - public Gender Gender { get; set; } = Gender.Male; + public Gender Gender { get; set; } = Gender.Male; - public Label HeaderLabel { get; set; } + public Label HeaderLabel { get; set; } - public bool IsHidden { get; set; } = false; + public bool IsHidden { get; set; } = false; - public bool HideName { get; set; } + public bool HideName { get; set; } - //Core Values - public Guid Id { get; set; } + //Core Values + public Guid Id { get; set; } - //Inventory/Spells/Equipment - public IItem[] Inventory { get; set; } = new IItem[Options.MaxInvItems]; + //Inventory/Spells/Equipment + public IItem[] Inventory { get; set; } = new IItem[Options.MaxInvItems]; - IReadOnlyList IEntity.Items => Inventory.ToList(); + IReadOnlyList IEntity.Items => Inventory.ToList(); - public bool InView { get; set; } = true; + public bool InView { get; set; } = true; - public bool IsMoving { get; set; } + public bool IsMoving { get; set; } - //Caching - public IMapInstance LatestMap { get; set; } + //Caching + public IMapInstance LatestMap { get; set; } - public int Level { get; set; } = 1; + public int Level { get; set; } = 1; - //Vitals & Stats - public long[] MaxVital { get; set; } = new long[Enum.GetValues().Length]; + //Vitals & Stats + public long[] MaxVital { get; set; } = new long[Enum.GetValues().Length]; - IReadOnlyList IEntity.MaxVitals => MaxVital.ToList(); + IReadOnlyList IEntity.MaxVitals => MaxVital.ToList(); - protected Pointf mOrigin = Pointf.Empty; + protected Pointf mOrigin = Pointf.Empty; - //Chat - private List mChatBubbles = new List(); + //Chat + private List mChatBubbles = new List(); - private Direction mDir; + private Direction mDir; - protected bool mDisposed; + protected bool mDisposed; - private long mLastUpdate; + private long mLastUpdate; - protected string mMySprite = ""; + protected string mMySprite = ""; - public Color Color { get; set; } = new Color(255, 255, 255, 255); + public Color Color { get; set; } = new Color(255, 255, 255, 255); - public virtual Direction MoveDir { get; set; } = Direction.None; + public virtual Direction MoveDir { get; set; } = Direction.None; - public long MoveTimer { get; set; } + public long MoveTimer { get; set; } - protected byte mRenderPriority = 1; + protected byte mRenderPriority = 1; - protected string mTransformedSprite = ""; + protected string mTransformedSprite = ""; - private long mWalkTimer; + private long mWalkTimer; - public int[] MyEquipment { get; set; } = new int[Options.EquipmentSlots.Count]; + public int[] MyEquipment { get; set; } = new int[Options.EquipmentSlots.Count]; - public string Name { get; set; } = ""; + public string Name { get; set; } = ""; - public Color NameColor { get; set; } = null; + public Color NameColor { get; set; } = null; - public float OffsetX { get; set; } + public float OffsetX { get; set; } - public float OffsetY { get; set; } + public float OffsetY { get; set; } - public bool Passable { get; set; } + public bool Passable { get; set; } - //Rendering Variables - public HashSet RenderList { get; set; } + //Rendering Variables + public HashSet RenderList { get; set; } - private Guid _spellCast; + private Guid _spellCast; - public Guid SpellCast + public Guid SpellCast + { + get => _spellCast; + set { - get => _spellCast; - set + if (value == SpellCast) { - if (value == SpellCast) - { - return; - } - - _spellCast = value; - LoadAnimationTexture(string.IsNullOrWhiteSpace(TransformedSprite) ? Sprite : TransformedSprite, SpriteAnimations.Cast); + return; } + + _spellCast = value; + LoadAnimationTexture(string.IsNullOrWhiteSpace(TransformedSprite) ? Sprite : TransformedSprite, SpriteAnimations.Cast); } + } - public Spell[] Spells { get; set; } = new Spell[Options.MaxPlayerSkills]; + public Spell[] Spells { get; set; } = new Spell[Options.MaxPlayerSkills]; - IReadOnlyList IEntity.Spells => Spells.Select(x => x.Id).ToList(); + IReadOnlyList IEntity.Spells => Spells.Select(x => x.Id).ToList(); - public int[] Stat { get; set; } = new int[Enum.GetValues().Length]; + public int[] Stat { get; set; } = new int[Enum.GetValues().Length]; - IReadOnlyList IEntity.Stats => Stat.ToList(); + IReadOnlyList IEntity.Stats => Stat.ToList(); - public GameTexture Texture { get; set; } + public GameTexture Texture { get; set; } - #region "Animation Textures and Timing" + #region "Animation Textures and Timing" - public SpriteAnimations SpriteAnimation { get; set; } = SpriteAnimations.Normal; + public SpriteAnimations SpriteAnimation { get; set; } = SpriteAnimations.Normal; - public Dictionary AnimatedTextures { get; set; } = - new Dictionary(); + public Dictionary AnimatedTextures { get; set; } = + new Dictionary(); - public int SpriteFrame { get; set; } = 0; + public int SpriteFrame { get; set; } = 0; - public long SpriteFrameTimer { get; set; } = -1; + public long SpriteFrameTimer { get; set; } = -1; - public long LastActionTime { get; set; } = -1; + public long LastActionTime { get; set; } = -1; - public long AutoTurnToTargetTimer { get; set; } = -1; + public long AutoTurnToTargetTimer { get; set; } = -1; - #endregion + #endregion - public EntityType Type { get; } + public EntityType Type { get; } - public NpcAggression Aggression { get; set; } + public NpcAggression Aggression { get; set; } - public long[] Vital { get; set; } = new long[Enum.GetValues().Length]; + public long[] Vital { get; set; } = new long[Enum.GetValues().Length]; - IReadOnlyList IEntity.Vitals => Vital.ToList(); + IReadOnlyList IEntity.Vitals => Vital.ToList(); - public int WalkFrame { get; set; } + public int WalkFrame { get; set; } - public FloatRect WorldPos { get; set; } = new FloatRect(); + public FloatRect WorldPos { get; set; } = new FloatRect(); - public bool IsHovered { get; set; } + public bool IsHovered { get; set; } - //Location Info - public byte X { get; set; } + //Location Info + public byte X { get; set; } - public byte Y { get; set; } + public byte Y { get; set; } - public byte Z { get; set; } + public byte Z { get; set; } - public Entity(Guid id, EntityPacket packet, EntityType entityType) - { - Id = id; - Type = entityType; - MapId = Guid.Empty; + public Entity(Guid id, EntityPacket packet, EntityType entityType) + { + Id = id; + Type = entityType; + MapId = Guid.Empty; - if (Id != Guid.Empty && Type != EntityType.Event) + if (Id != Guid.Empty && Type != EntityType.Event) + { + for (var i = 0; i < Options.MaxInvItems; i++) { - for (var i = 0; i < Options.MaxInvItems; i++) - { - Inventory[i] = new Item(); - } - - for (var i = 0; i < Options.MaxPlayerSkills; i++) - { - Spells[i] = new Spell(); - } - - for (var i = 0; i < Options.EquipmentSlots.Count; i++) - { - Equipment[i] = Guid.Empty; - MyEquipment[i] = -1; - } + Inventory[i] = new Item(); } - AnimationTimer = Timing.Global.MillisecondsUtc + Globals.Random.Next(0, 500); + for (var i = 0; i < Options.MaxPlayerSkills; i++) + { + Spells[i] = new Spell(); + } - //TODO Remove because fixed orrrrr change the exception text - if (Options.EquipmentSlots.Count == 0) + for (var i = 0; i < Options.EquipmentSlots.Count; i++) { - throw new Exception("What the fuck is going on!?!?!?!?!?!"); + Equipment[i] = Guid.Empty; + MyEquipment[i] = -1; } + } - Load(packet); + AnimationTimer = Timing.Global.MillisecondsUtc + Globals.Random.Next(0, 500); + + //TODO Remove because fixed orrrrr change the exception text + if (Options.EquipmentSlots.Count == 0) + { + throw new Exception("What the fuck is going on!?!?!?!?!?!"); } - //Status effects - public List Status { get; private set; } = new List(); + Load(packet); + } - IReadOnlyList IEntity.Status => Status; + //Status effects + public List Status { get; private set; } = new List(); - public Pointf Origin => LatestMap == default ? Pointf.Empty : mOrigin; + IReadOnlyList IEntity.Status => Status; - protected virtual Pointf CenterOffset => (Texture == default) ? Pointf.Empty : (Pointf.UnitY * Texture.Center.Y / Options.Instance.Sprites.Directions); + public Pointf Origin => LatestMap == default ? Pointf.Empty : mOrigin; - public Pointf Center => Origin - CenterOffset; + protected virtual Pointf CenterOffset => (Texture == default) ? Pointf.Empty : (Pointf.UnitY * Texture.Center.Y / Options.Instance.Sprites.Directions); - public Direction Dir - { - get => mDir; - set => mDir = (Direction)((int)(value + Options.Instance.MapOpts.MovementDirections) % Options.Instance.MapOpts.MovementDirections); - } + public Pointf Center => Origin - CenterOffset; + + public Direction Dir + { + get => mDir; + set => mDir = (Direction)((int)(value + Options.Instance.MapOpts.MovementDirections) % Options.Instance.MapOpts.MovementDirections); + } - private Direction mLastDirection = Direction.Down; + private Direction mLastDirection = Direction.Down; - public virtual string TransformedSprite + public virtual string TransformedSprite + { + get => mTransformedSprite; + set { - get => mTransformedSprite; - set + if (mTransformedSprite == value) { - if (mTransformedSprite == value) - { - return; - } + return; + } - mTransformedSprite = value; + mTransformedSprite = value; - var textureName = string.IsNullOrEmpty(mTransformedSprite) ? mMySprite : mTransformedSprite; - LoadTextures(textureName); - } + var textureName = string.IsNullOrEmpty(mTransformedSprite) ? mMySprite : mTransformedSprite; + LoadTextures(textureName); } + } - public virtual string Sprite + public virtual string Sprite + { + get => mMySprite; + set { - get => mMySprite; - set + if (mMySprite == value) { - if (mMySprite == value) - { - return; - } - - mMySprite = value; - LoadTextures(mMySprite); + return; } + + mMySprite = value; + LoadTextures(mMySprite); } + } - public virtual int SpriteFrames + public virtual int SpriteFrames + { + get { - get + switch (SpriteAnimation) { - switch (SpriteAnimation) - { - case SpriteAnimations.Normal: - return Options.Instance.Sprites.NormalFrames; - case SpriteAnimations.Idle: - return Options.Instance.Sprites.IdleFrames; - case SpriteAnimations.Attack: - return Options.Instance.Sprites.AttackFrames; - case SpriteAnimations.Shoot: - return Options.Instance.Sprites.ShootFrames; - case SpriteAnimations.Cast: - return Options.Instance.Sprites.CastFrames; - case SpriteAnimations.Weapon: - return Options.Instance.Sprites.WeaponFrames; - } + case SpriteAnimations.Normal: + return Options.Instance.Sprites.NormalFrames; + case SpriteAnimations.Idle: + return Options.Instance.Sprites.IdleFrames; + case SpriteAnimations.Attack: + return Options.Instance.Sprites.AttackFrames; + case SpriteAnimations.Shoot: + return Options.Instance.Sprites.ShootFrames; + case SpriteAnimations.Cast: + return Options.Instance.Sprites.CastFrames; + case SpriteAnimations.Weapon: + return Options.Instance.Sprites.WeaponFrames; + } - return Options.Instance.Sprites.NormalFrames; + return Options.Instance.Sprites.NormalFrames; - } } + } - public IMapInstance? MapInstance => Maps.MapInstance.Get(MapId); + public IMapInstance? MapInstance => Maps.MapInstance.Get(MapId); - public virtual Guid MapId { get; set; } + public virtual Guid MapId { get; set; } + + //Deserializing + public virtual void Load(EntityPacket packet) + { + if (packet == null) + { + return; + } - //Deserializing - public virtual void Load(EntityPacket packet) + MapId = packet.MapId; + Name = packet.Name; + Sprite = packet.Sprite; + Color = packet.Color; + Face = packet.Face; + Level = packet.Level; + X = packet.X; + Y = packet.Y; + Z = packet.Z; + Dir = (Direction)packet.Dir; + Passable = packet.Passable; + HideName = packet.HideName; + IsHidden = packet.HideEntity; + NameColor = packet.NameColor; + HeaderLabel = new Label(packet.HeaderLabel.Label, packet.HeaderLabel.Color); + FooterLabel = new Label(packet.FooterLabel.Label, packet.FooterLabel.Color); + + var animsToClear = new List(); + var animsToAdd = new List(); + for (var i = 0; i < packet.Animations.Length; i++) { - if (packet == null) + var anim = AnimationBase.Get(packet.Animations[i]); + if (anim != null) { - return; + animsToAdd.Add(anim); } + } - MapId = packet.MapId; - Name = packet.Name; - Sprite = packet.Sprite; - Color = packet.Color; - Face = packet.Face; - Level = packet.Level; - X = packet.X; - Y = packet.Y; - Z = packet.Z; - Dir = (Direction)packet.Dir; - Passable = packet.Passable; - HideName = packet.HideName; - IsHidden = packet.HideEntity; - NameColor = packet.NameColor; - HeaderLabel = new Label(packet.HeaderLabel.Label, packet.HeaderLabel.Color); - FooterLabel = new Label(packet.FooterLabel.Label, packet.FooterLabel.Color); - - var animsToClear = new List(); - var animsToAdd = new List(); - for (var i = 0; i < packet.Animations.Length; i++) - { - var anim = AnimationBase.Get(packet.Animations[i]); - if (anim != null) - { - animsToAdd.Add(anim); - } + foreach (var anim in Animations) + { + animsToClear.Add(anim); + if (!anim.InfiniteLoop) + { + animsToClear.Remove(anim); } - - foreach (var anim in Animations) + else { - animsToClear.Add(anim); - if (!anim.InfiniteLoop) - { - animsToClear.Remove(anim); - } - else + foreach (var addedAnim in animsToAdd) { - foreach (var addedAnim in animsToAdd) + if (addedAnim.Id == anim.MyBase.Id) { - if (addedAnim.Id == anim.MyBase.Id) - { - animsToClear.Remove(anim); - animsToAdd.Remove(addedAnim); + animsToClear.Remove(anim); + animsToAdd.Remove(addedAnim); - break; - } + break; } + } - foreach (var equipAnim in EquipmentAnimations) + foreach (var equipAnim in EquipmentAnimations) + { + if (equipAnim == anim) { - if (equipAnim == anim) - { - animsToClear.Remove(anim); - } + animsToClear.Remove(anim); } } } + } - ClearAnimations(animsToClear); - AddAnimations(animsToAdd); + ClearAnimations(animsToClear); + AddAnimations(animsToAdd); - Vital = packet.Vital; - MaxVital = packet.MaxVital; + Vital = packet.Vital; + MaxVital = packet.MaxVital; - //Update status effects - Status.Clear(); + //Update status effects + Status.Clear(); - if (packet.StatusEffects == null) - { - Log.Warn($"'{nameof(packet)}.{nameof(packet.StatusEffects)}' is null."); - } - else + if (packet.StatusEffects == null) + { + Log.Warn($"'{nameof(packet)}.{nameof(packet.StatusEffects)}' is null."); + } + else + { + foreach (var status in packet.StatusEffects) { - foreach (var status in packet.StatusEffects) - { - var instance = new Status( - status.SpellId, status.Type, status.TransformSprite, status.TimeRemaining, status.TotalDuration - ); + var instance = new Status( + status.SpellId, status.Type, status.TransformSprite, status.TimeRemaining, status.TotalDuration + ); - Status?.Add(instance); + Status?.Add(instance); - if (instance.Type == SpellEffect.Shield) - { - instance.Shield = status.VitalShields; - } + if (instance.Type == SpellEffect.Shield) + { + instance.Shield = status.VitalShields; } } + } - SortStatuses(); - Stat = packet.Stats; + SortStatuses(); + Stat = packet.Stats; - mDisposed = false; + mDisposed = false; - //Status effects box update - if (Globals.Me == null) - { - Log.Warn($"'{nameof(Globals.Me)}' is null."); - } - else + //Status effects box update + if (Globals.Me == null) + { + Log.Warn($"'{nameof(Globals.Me)}' is null."); + } + else + { + if (Id == Globals.Me.Id) { - if (Id == Globals.Me.Id) + if (Interface.Interface.GameUi == null) { - if (Interface.Interface.GameUi == null) - { - Log.Warn($"'{nameof(Interface.Interface.GameUi)}' is null."); - } - else - { - if (Interface.Interface.GameUi.PlayerStatusWindow == null) - { - Log.Warn($"'{nameof(Interface.Interface.GameUi.PlayerStatusWindow)}' is null."); - } - else - { - Interface.Interface.GameUi.PlayerStatusWindow.ShouldUpdateStatuses = true; - } - } + Log.Warn($"'{nameof(Interface.Interface.GameUi)}' is null."); } - else if (Id != Guid.Empty && Id == Globals.Me.TargetIndex) + else { - if (Globals.Me.TargetBox == null) + if (Interface.Interface.GameUi.PlayerStatusWindow == null) { - Log.Warn($"'{nameof(Globals.Me.TargetBox)}' is null."); + Log.Warn($"'{nameof(Interface.Interface.GameUi.PlayerStatusWindow)}' is null."); } else { - Globals.Me.TargetBox.ShouldUpdateStatuses = true; + Interface.Interface.GameUi.PlayerStatusWindow.ShouldUpdateStatuses = true; } } } - } - - public void AddAnimations(List anims) - { - foreach (var anim in anims) + else if (Id != Guid.Empty && Id == Globals.Me.TargetIndex) { - Animations.Add(new Animation(anim, true, false, -1, this)); + if (Globals.Me.TargetBox == null) + { + Log.Warn($"'{nameof(Globals.Me.TargetBox)}' is null."); + } + else + { + Globals.Me.TargetBox.ShouldUpdateStatuses = true; + } } } + } - public virtual bool IsAllyOf(Player en) + public void AddAnimations(List anims) + { + foreach (var anim in anims) { - if (en == null || MapInstance == default || en.MapInstance == default) - { - return false; - } - - // Resources have no allies - if (Type == EntityType.Resource) - { - return false; - } - - // Events ONLY have allies - if (Type == EntityType.Event) - { - return true; - } + Animations.Add(new Animation(anim, true, false, -1, this)); + } + } - // Yourself is always an ally - if (en.Id == Id) - { - return true; - } + public virtual bool IsAllyOf(Player en) + { + if (en == null || MapInstance == default || en.MapInstance == default) + { + return false; + } + // Resources have no allies + if (Type == EntityType.Resource) + { return false; } - public void ClearAnimations(List anims) + // Events ONLY have allies + if (Type == EntityType.Event) { - if (anims == null) - { - anims = Animations; - } + return true; + } - if (anims.Count > 0) - { - for (var i = 0; i < anims.Count; i++) - { - anims[i].Dispose(); - Animations.Remove(anims[i]); - } - } + // Yourself is always an ally + if (en.Id == Id) + { + return true; } - public virtual bool IsDisposed() + return false; + } + + public void ClearAnimations(List anims) + { + if (anims == null) { - return mDisposed; + anims = Animations; } - public virtual void Dispose() + if (anims.Count > 0) { - if (RenderList != null) + for (var i = 0; i < anims.Count; i++) { - RenderList.Remove(this); + anims[i].Dispose(); + Animations.Remove(anims[i]); } - - ClearAnimations(null); - mDisposed = true; } + } - //Returns the amount of time required to traverse 1 tile - public virtual float GetMovementTime() + public virtual bool IsDisposed() + { + return mDisposed; + } + + public virtual void Dispose() + { + if (RenderList != null) { - var time = 1000f / (float)(1 + Math.Log(Stat[(int)Enums.Stat.Speed])); - if (Dir > Direction.Right) - { - time *= MathHelper.UnitDiagonalLength; - } + RenderList.Remove(this); + } - if (IsBlocking) - { - time += time * Options.BlockingSlow; - } + ClearAnimations(null); + mDisposed = true; + } + + //Returns the amount of time required to traverse 1 tile + public virtual float GetMovementTime() + { + var time = 1000f / (float)(1 + Math.Log(Stat[(int)Enums.Stat.Speed])); + if (Dir > Direction.Right) + { + time *= MathHelper.UnitDiagonalLength; + } - return Math.Min(1000f, time); + if (IsBlocking) + { + time += time * Options.BlockingSlow; } - public override string ToString() => Name; + return Math.Min(1000f, time); + } + + public override string ToString() => Name; - //Movement Processing - public virtual bool Update() + //Movement Processing + public virtual bool Update() + { + if (mDisposed) { - if (mDisposed) - { - LatestMap = null; + LatestMap = null; - return false; - } + return false; + } - if (LatestMap?.Id != MapId) - { - LatestMap = Maps.MapInstance.Get(MapId); - } + if (LatestMap?.Id != MapId) + { + LatestMap = Maps.MapInstance.Get(MapId); + } - if (LatestMap == null || !LatestMap.InView()) - { - Globals.EntitiesToDispose.Add(Id); + if (LatestMap == null || !LatestMap.InView()) + { + Globals.EntitiesToDispose.Add(Id); - return false; - } + return false; + } - RenderList = DetermineRenderOrder(RenderList, LatestMap); - if (mLastUpdate == 0) - { - mLastUpdate = Timing.Global.Milliseconds; - } + RenderList = DetermineRenderOrder(RenderList, LatestMap); + if (mLastUpdate == 0) + { + mLastUpdate = Timing.Global.Milliseconds; + } - var ecTime = (float)(Timing.Global.Milliseconds - mLastUpdate); - elapsedtime = ecTime; - if (Dashing != null) + var ecTime = (float)(Timing.Global.Milliseconds - mLastUpdate); + elapsedtime = ecTime; + if (Dashing != null) + { + WalkFrame = Options.Instance.Sprites.NormalDashFrame; //Fix the frame whilst dashing + } + else if (mWalkTimer < Timing.Global.Milliseconds) + { + if (!IsMoving && DashQueue.Count > 0) { - WalkFrame = Options.Instance.Sprites.NormalDashFrame; //Fix the frame whilst dashing + Dashing = DashQueue.Dequeue(); + Dashing.Start(this); + OffsetX = 0; + OffsetY = 0; + DashTimer = Timing.Global.Milliseconds + Options.MaxDashSpeed; } - else if (mWalkTimer < Timing.Global.Milliseconds) + else { - if (!IsMoving && DashQueue.Count > 0) + if (IsMoving) { - Dashing = DashQueue.Dequeue(); - Dashing.Start(this); - OffsetX = 0; - OffsetY = 0; - DashTimer = Timing.Global.Milliseconds + Options.MaxDashSpeed; + WalkFrame++; + if (WalkFrame >= SpriteFrames) + { + WalkFrame = 0; + } } else { - if (IsMoving) + if (WalkFrame > 0 && WalkFrame / SpriteFrames < 0.7f) { - WalkFrame++; - if (WalkFrame >= SpriteFrames) - { - WalkFrame = 0; - } + WalkFrame = SpriteFrames / 2; } else { - if (WalkFrame > 0 && WalkFrame / SpriteFrames < 0.7f) - { - WalkFrame = SpriteFrames / 2; - } - else - { - WalkFrame = 0; - } + WalkFrame = 0; } - - mWalkTimer = Timing.Global.Milliseconds + Options.Instance.Sprites.MovingFrameDuration; } + + mWalkTimer = Timing.Global.Milliseconds + Options.Instance.Sprites.MovingFrameDuration; } + } - if (Dashing != null) + if (Dashing != null) + { + if (Dashing.Update(this)) { - if (Dashing.Update(this)) - { - OffsetX = Dashing.GetXOffset(); - OffsetY = Dashing.GetYOffset(); - } - else - { - OffsetX = 0; - OffsetY = 0; - } + OffsetX = Dashing.GetXOffset(); + OffsetY = Dashing.GetYOffset(); } - else if (IsMoving) + else { - var displacementTime = ecTime * Options.TileHeight / GetMovementTime(); - - PickLastDirection(Dir); - - switch (Dir) - { - case Direction.Up: - OffsetY -= displacementTime; - OffsetX = 0; - if (OffsetY < 0) - { - OffsetY = 0; - } + OffsetX = 0; + OffsetY = 0; + } + } + else if (IsMoving) + { + var displacementTime = ecTime * Options.TileHeight / GetMovementTime(); - break; + PickLastDirection(Dir); - case Direction.Down: - OffsetY += displacementTime; - OffsetX = 0; - if (OffsetY > 0) - { - OffsetY = 0; - } + switch (Dir) + { + case Direction.Up: + OffsetY -= displacementTime; + OffsetX = 0; + if (OffsetY < 0) + { + OffsetY = 0; + } - break; + break; - case Direction.Left: - OffsetX -= displacementTime; + case Direction.Down: + OffsetY += displacementTime; + OffsetX = 0; + if (OffsetY > 0) + { OffsetY = 0; - if (OffsetX < 0) - { - OffsetX = 0; - } + } - break; + break; - case Direction.Right: - OffsetX += displacementTime; - OffsetY = 0; - if (OffsetX > 0) - { - OffsetX = 0; - } + case Direction.Left: + OffsetX -= displacementTime; + OffsetY = 0; + if (OffsetX < 0) + { + OffsetX = 0; + } - break; - case Direction.UpLeft: - OffsetY -= displacementTime; - OffsetX -= displacementTime; - if (OffsetY < 0) - { - OffsetY = 0; - } + break; - if (OffsetX < 0) - { - OffsetX = 0; - } + case Direction.Right: + OffsetX += displacementTime; + OffsetY = 0; + if (OffsetX > 0) + { + OffsetX = 0; + } - break; - case Direction.UpRight: - OffsetY -= displacementTime; - OffsetX += displacementTime; - if (OffsetY < 0) - { - OffsetY = 0; - } + break; + case Direction.UpLeft: + OffsetY -= displacementTime; + OffsetX -= displacementTime; + if (OffsetY < 0) + { + OffsetY = 0; + } - if (OffsetX > 0) - { - OffsetX = 0; - } + if (OffsetX < 0) + { + OffsetX = 0; + } - break; - case Direction.DownLeft: - OffsetY += displacementTime; - OffsetX -= displacementTime; - if (OffsetY > 0) - { - OffsetY = 0; - } + break; + case Direction.UpRight: + OffsetY -= displacementTime; + OffsetX += displacementTime; + if (OffsetY < 0) + { + OffsetY = 0; + } - if (OffsetX < 0) - { - OffsetX = 0; - } + if (OffsetX > 0) + { + OffsetX = 0; + } + break; + case Direction.DownLeft: + OffsetY += displacementTime; + OffsetX -= displacementTime; + if (OffsetY > 0) + { + OffsetY = 0; + } - break; - case Direction.DownRight: - OffsetY += displacementTime; - OffsetX += displacementTime; - if (OffsetY > 0) - { - OffsetY = 0; - } + if (OffsetX < 0) + { + OffsetX = 0; + } - if (OffsetX > 0) - { - OffsetX = 0; - } - break; - } + break; + case Direction.DownRight: + OffsetY += displacementTime; + OffsetX += displacementTime; + if (OffsetY > 0) + { + OffsetY = 0; + } - if (OffsetX == 0 && OffsetY == 0) - { - IsMoving = false; - } + if (OffsetX > 0) + { + OffsetX = 0; + } + + break; } - //Check to see if we should start or stop equipment animations - if (Equipment.Length == Options.EquipmentSlots.Count) + if (OffsetX == 0 && OffsetY == 0) { - for (var z = 0; z < Options.EquipmentSlots.Count; z++) + IsMoving = false; + } + } + + //Check to see if we should start or stop equipment animations + if (Equipment.Length == Options.EquipmentSlots.Count) + { + for (var z = 0; z < Options.EquipmentSlots.Count; z++) + { + if (Equipment[z] != Guid.Empty && (this != Globals.Me || MyEquipment[z] < Options.MaxInvItems)) { - if (Equipment[z] != Guid.Empty && (this != Globals.Me || MyEquipment[z] < Options.MaxInvItems)) + var itemId = Guid.Empty; + if (this == Globals.Me) { - var itemId = Guid.Empty; - if (this == Globals.Me) - { - var slot = MyEquipment[z]; - if (slot > -1) - { - itemId = Inventory[slot].ItemId; - } - } - else + var slot = MyEquipment[z]; + if (slot > -1) { - itemId = Equipment[z]; + itemId = Inventory[slot].ItemId; } + } + else + { + itemId = Equipment[z]; + } - var itm = ItemBase.Get(itemId); - AnimationBase anim = null; - if (itm != null) - { - anim = itm.EquipmentAnimation; - } + var itm = ItemBase.Get(itemId); + AnimationBase anim = null; + if (itm != null) + { + anim = itm.EquipmentAnimation; + } - if (anim != null) + if (anim != null) + { + if (EquipmentAnimations[z] != null && + (EquipmentAnimations[z].MyBase != anim || EquipmentAnimations[z].Disposed())) { - if (EquipmentAnimations[z] != null && - (EquipmentAnimations[z].MyBase != anim || EquipmentAnimations[z].Disposed())) - { - EquipmentAnimations[z].Dispose(); - Animations.Remove(EquipmentAnimations[z]); - EquipmentAnimations[z] = null; - } - - if (EquipmentAnimations[z] == null) - { - EquipmentAnimations[z] = new Animation(anim, true, true, -1, this); - Animations.Add(EquipmentAnimations[z]); - } + EquipmentAnimations[z].Dispose(); + Animations.Remove(EquipmentAnimations[z]); + EquipmentAnimations[z] = null; } - else + + if (EquipmentAnimations[z] == null) { - if (EquipmentAnimations[z] != null) - { - EquipmentAnimations[z].Dispose(); - Animations.Remove(EquipmentAnimations[z]); - EquipmentAnimations[z] = null; - } + EquipmentAnimations[z] = new Animation(anim, true, true, -1, this); + Animations.Add(EquipmentAnimations[z]); } } else @@ -824,1615 +814,1623 @@ public virtual bool Update() } } } - } - - var chatbubbles = mChatBubbles.ToArray(); - foreach (var chatbubble in chatbubbles) - { - if (!chatbubble.Update()) - { - mChatBubbles.Remove(chatbubble); - } - } - - if (AnimationTimer < Timing.Global.MillisecondsUtc) - { - AnimationTimer = Timing.Global.MillisecondsUtc + 200; - AnimationFrame++; - if (AnimationFrame >= SpriteFrames) - { - AnimationFrame = 0; - } - } - - CalculateOrigin(); - - List animsToRemove = null; - foreach (var animInstance in Animations) - { - animInstance.Update(); - - //If disposed mark to be removed and continue onward - if (animInstance.Disposed()) + else { - if (animsToRemove == null) + if (EquipmentAnimations[z] != null) { - animsToRemove = new List(); + EquipmentAnimations[z].Dispose(); + Animations.Remove(EquipmentAnimations[z]); + EquipmentAnimations[z] = null; } - - animsToRemove.Add(animInstance); - - continue; } - - if (IsStealthed || IsHidden) - { - animInstance.Hide(); - } - else - { - animInstance.Show(); - } - - var animationDirection = animInstance.AutoRotate ? Dir : default; - animInstance.SetPosition( - (int)Math.Ceiling(Center.X), - (int)Math.Ceiling(Center.Y), - X, - Y, - MapId, - animationDirection, Z - ); } + } - if (animsToRemove != null) + var chatbubbles = mChatBubbles.ToArray(); + foreach (var chatbubble in chatbubbles) + { + if (!chatbubble.Update()) { - foreach (var anim in animsToRemove) - { - Animations.Remove(anim); - } + mChatBubbles.Remove(chatbubble); } - - mLastUpdate = Timing.Global.Milliseconds; - - UpdateSpriteAnimation(); - - return true; } - public virtual int CalculateAttackTime() + if (AnimationTimer < Timing.Global.MillisecondsUtc) { - //If this is an npc we don't know it's attack time. Luckily the server provided it! - if (this != Globals.Me && AttackTime > -1) + AnimationTimer = Timing.Global.MillisecondsUtc + 200; + AnimationFrame++; + if (AnimationFrame >= SpriteFrames) { - return AttackTime; + AnimationFrame = 0; } - - //Otherwise return the legacy attack speed calculation - return (int)(Options.MaxAttackRate + - (Options.MinAttackRate - Options.MaxAttackRate) * - (((float)Options.MaxStatValue - Stat[(int)Enums.Stat.Speed]) / - Options.MaxStatValue)); } - /// - /// Returns whether this entity is Stealthed or not. - /// - public virtual bool IsStealthed => this != Globals.Me && Status.Any(t => t.Type == SpellEffect.Stealth); - - /// - /// Returns whether this entity should be drawn. - /// - public virtual bool ShouldDraw => !IsHidden && (!IsStealthed || this == Globals.Me || Globals.Me.IsInMyParty(Id)); + CalculateOrigin(); - /// - /// Returns whether the name of this entity should be drawn. - /// - public virtual bool ShouldDrawName + List animsToRemove = null; + foreach (var animInstance in Animations) { - get + animInstance.Update(); + + //If disposed mark to be removed and continue onward + if (animInstance.Disposed()) { - // Return if the map instance is null or the name is empty or not set to be drawn. - if (MapInstance == null || string.IsNullOrWhiteSpace(Name) || HideName || !ShouldDraw) + if (animsToRemove == null) { - return false; + animsToRemove = new List(); } - // Look up the mouse position and convert it to a world point. - var mousePos = Graphics.ConvertToWorldPoint(Globals.InputManager.MousePosition); + animsToRemove.Add(animInstance); - // Entity is considered hovered if the mouse is over its world position and not hovering over the GUI. - IsHovered = WorldPos.Contains(mousePos.X, mousePos.Y) && !Interface.Interface.MouseHitGui(); + continue; + } - // Check the type of entity and return whether its name should be drawn based on settings and conditions. - switch (this) - { - case Projectile _: - case Resource _: - return false; + if (IsStealthed || IsHidden) + { + animInstance.Hide(); + } + else + { + animInstance.Show(); + } - case Event _: - return true; + var animationDirection = animInstance.AutoRotate ? Dir : default; + animInstance.SetPosition( + (int)Math.Ceiling(Center.X), + (int)Math.Ceiling(Center.Y), + X, + Y, + MapId, + animationDirection, Z + ); + } - case Player player: - if (IsHovered) - { - return true; - } + if (animsToRemove != null) + { + foreach (var anim in animsToRemove) + { + Animations.Remove(anim); + } + } - var me = Globals.Me; + mLastUpdate = Timing.Global.Milliseconds; - if (Globals.Database.MyOverheadInfo && player.Id == me.Id) - { - return true; - } + UpdateSpriteAnimation(); - if (Globals.Database.PlayerOverheadInfo && player.Id != me.Id) - { - return true; - } + return true; + } - if (Globals.Database.PartyMemberOverheadInfo && me.IsInMyParty(player)) - { - return true; - } + public virtual int CalculateAttackTime() + { + //If this is an npc we don't know it's attack time. Luckily the server provided it! + if (this != Globals.Me && AttackTime > -1) + { + return AttackTime; + } - if (Globals.Database.FriendOverheadInfo && me.IsFriend(player)) - { - return true; - } + //Otherwise return the legacy attack speed calculation + return (int)(Options.MaxAttackRate + + (Options.MinAttackRate - Options.MaxAttackRate) * + (((float)Options.MaxStatValue - Stat[(int)Enums.Stat.Speed]) / + Options.MaxStatValue)); + } - return Globals.Database.GuildMemberOverheadInfo && me.IsGuildMate(player); + /// + /// Returns whether this entity is Stealthed or not. + /// + public virtual bool IsStealthed => this != Globals.Me && Status.Any(t => t.Type == SpellEffect.Stealth); - default: - return IsHovered || Globals.Database.NpcOverheadInfo; - } - } - } + /// + /// Returns whether this entity should be drawn. + /// + public virtual bool ShouldDraw => !IsHidden && (!IsStealthed || this == Globals.Me || Globals.Me.IsInMyParty(Id)); - public virtual HashSet? DetermineRenderOrder(HashSet? existingRenderSet, IMapInstance? map) + /// + /// Returns whether the name of this entity should be drawn. + /// + public virtual bool ShouldDrawName + { + get { - existingRenderSet?.Remove(this); - - var playerMap = Globals.Me?.MapInstance; - if (map == default || playerMap == default) + // Return if the map instance is null or the name is empty or not set to be drawn. + if (MapInstance == null || string.IsNullOrWhiteSpace(Name) || HideName || !ShouldDraw) { - return default; + return false; } - var gridX = playerMap.GridX; - var gridY = playerMap.GridY; - for (var x = gridX - 1; x <= gridX + 1; x++) + // Look up the mouse position and convert it to a world point. + var mousePos = Graphics.ConvertToWorldPoint(Globals.InputManager.MousePosition); + + // Entity is considered hovered if the mouse is over its world position and not hovering over the GUI. + IsHovered = WorldPos.Contains(mousePos.X, mousePos.Y) && !Interface.Interface.MouseHitGui(); + + // Check the type of entity and return whether its name should be drawn based on settings and conditions. + switch (this) { - for (var y = gridY - 1; y <= gridY + 1; y++) - { - if (x < 0 || x >= Globals.MapGridWidth || y < 0 || y >= Globals.MapGridHeight) - { - continue; - } + case Projectile _: + case Resource _: + return false; - var mapIdOnGrid = Globals.MapGrid[x, y]; - if (mapIdOnGrid != MapId) - { - continue; - } + case Event _: + return true; - var priority = mRenderPriority; - if (Z != 0) + case Player player: + if (IsHovered) { - priority += 3; + return true; } - HashSet? renderSet = default; - int entityY; + var me = Globals.Me; - if (y == gridY - 1) + if (Globals.Database.MyOverheadInfo && player.Id == me.Id) { - entityY = Options.MapHeight + Y; + return true; } - else if (y == gridY) + + if (Globals.Database.PlayerOverheadInfo && player.Id != me.Id) { - entityY = Options.MapHeight * 2 + Y; + return true; } - else + + if (Globals.Database.PartyMemberOverheadInfo && me.IsInMyParty(player)) { - entityY = Options.MapHeight * 3 + Y; + return true; } - entityY = (int)Math.Floor(entityY + OffsetY / Options.TileHeight); - - var renderingEntities = Graphics.RenderingEntities; - if (priority >= renderingEntities.GetLength(0) || entityY >= renderingEntities.GetLength(1)) + if (Globals.Database.FriendOverheadInfo && me.IsFriend(player)) { - return renderSet; + return true; } - renderSet = renderingEntities[priority, entityY]; - renderSet.Add(this); + return Globals.Database.GuildMemberOverheadInfo && me.IsGuildMate(player); - return renderSet; - } + default: + return IsHovered || Globals.Database.NpcOverheadInfo; } - - return existingRenderSet; } + } + + public virtual HashSet? DetermineRenderOrder(HashSet? existingRenderSet, IMapInstance? map) + { + existingRenderSet?.Remove(this); - //Rendering Functions - public virtual void Draw() + var playerMap = Globals.Me?.MapInstance; + if (map == default || playerMap == default) { - if (IsHidden) - { - return; //Don't draw if the entity is hidden - } + return default; + } - WorldPos.Reset(); - var map = Maps.MapInstance.Get(MapId); - if (map == null || !Globals.GridMaps.Contains(MapId)) + var gridX = playerMap.GridX; + var gridY = playerMap.GridY; + for (var x = gridX - 1; x <= gridX + 1; x++) + { + for (var y = gridY - 1; y <= gridY + 1; y++) { - return; - } + if (x < 0 || x >= Globals.MapGridWidth || y < 0 || y >= Globals.MapGridHeight) + { + continue; + } - var sprite = ""; - // Copy the actual render color, because we'll be editing it later and don't want to overwrite it. - var renderColor = new Color(Color.A, Color.R, Color.G, Color.B); + var mapIdOnGrid = Globals.MapGrid[x, y]; + if (mapIdOnGrid != MapId) + { + continue; + } - string transformedSprite = ""; + var priority = mRenderPriority; + if (Z != 0) + { + priority += 3; + } - // Loop through the entity status list. - for (var n = 0; n < Status.Count; n++) - { - var status = Status[n]; + HashSet? renderSet = default; + int entityY; - switch (status.Type) + if (y == gridY - 1) { - // If the entity is transformed: apply that sprite instead. - case SpellEffect.Transform: - transformedSprite = sprite = status.Data; - break; + entityY = Options.MapHeight + Y; + } + else if (y == gridY) + { + entityY = Options.MapHeight * 2 + Y; + } + else + { + entityY = Options.MapHeight * 3 + Y; + } - // If entity is stealth, don't render unless the entity is the player or is within their party. - case SpellEffect.Stealth: - if (this != Globals.Me && !(this is Player player && Globals.Me.IsInMyParty(player))) - { - return; - } + entityY = (int)Math.Floor(entityY + OffsetY / Options.TileHeight); - renderColor.A /= 2; - break; + var renderingEntities = Graphics.RenderingEntities; + if (priority >= renderingEntities.GetLength(0) || entityY >= renderingEntities.GetLength(1)) + { + return renderSet; } - } - - if (transformedSprite != TransformedSprite) - { - TransformedSprite = transformedSprite; - } - //Check if there is no transformed sprite set - if (string.IsNullOrEmpty(sprite)) - { - sprite = Sprite; - Sprite = sprite; - } + renderSet = renderingEntities[priority, entityY]; + renderSet.Add(this); - if (!AnimatedTextures.TryGetValue(SpriteAnimation, out var texture)) - { - texture = Texture; + return renderSet; } + } - if (texture == default) - { - // We don't have a texture to render, but we still want this to be targetable. - WorldPos = new FloatRect( - map.GetX() + X * Options.TileWidth + OffsetX, - map.GetY() + Y * Options.TileHeight + OffsetY, - Options.TileWidth, - Options.TileHeight); - return; - } + return existingRenderSet; + } - var spriteRow = PickSpriteRow(Dir); + //Rendering Functions + public virtual void Draw() + { + if (IsHidden) + { + return; //Don't draw if the entity is hidden + } - var frameWidth = texture.GetWidth() / SpriteFrames; - var frameHeight = texture.GetHeight() / Options.Instance.Sprites.Directions; + WorldPos.Reset(); + var map = Maps.MapInstance.Get(MapId); + if (map == null || !Globals.GridMaps.Contains(MapId)) + { + return; + } - var frame = SpriteFrame; - if (Options.AnimatedSprites.Contains(sprite.ToLower())) - { - frame = AnimationFrame; - } - else if (SpriteAnimation == SpriteAnimations.Normal) - { - frame = NormalSpriteAnimationFrame; - } + var sprite = ""; + // Copy the actual render color, because we'll be editing it later and don't want to overwrite it. + var renderColor = new Color(Color.A, Color.R, Color.G, Color.B); - var srcRectangle = new FloatRect(frame * frameWidth, spriteRow * frameHeight, frameWidth, frameHeight); - var destRectangle = new FloatRect( - (int)Math.Ceiling(Origin.X - frameWidth / 2f), - (int)Math.Ceiling(Origin.Y - frameHeight), - srcRectangle.Width, - srcRectangle.Height - ); + string transformedSprite = ""; - WorldPos = destRectangle; + // Loop through the entity status list. + for (var n = 0; n < Status.Count; n++) + { + var status = Status[n]; - //Order the layers of paperdolls and sprites - for (var z = 0; z < Options.PaperdollOrder[(int)mLastDirection].Count; z++) + switch (status.Type) { - var paperdoll = Options.PaperdollOrder[(int)mLastDirection][z]; - var equipSlot = Options.EquipmentSlots.IndexOf(paperdoll); + // If the entity is transformed: apply that sprite instead. + case SpellEffect.Transform: + transformedSprite = sprite = status.Data; + break; - //Check for player - if (string.Equals("Player", paperdoll, StringComparison.Ordinal)) - { - Graphics.DrawGameTexture(texture, srcRectangle, destRectangle, renderColor); - } - else if (equipSlot > -1) - { - //Don't render the paperdolls if they have transformed. - if (sprite == Sprite && Equipment.Length == Options.EquipmentSlots.Count) + // If entity is stealth, don't render unless the entity is the player or is within their party. + case SpellEffect.Stealth: + if (this != Globals.Me && !(this is Player player && Globals.Me.IsInMyParty(player))) { - if (Equipment[equipSlot] != Guid.Empty && this != Globals.Me || - MyEquipment[equipSlot] < Options.MaxInvItems) - { - var itemId = Guid.Empty; - if (this == Globals.Me) - { - var slot = MyEquipment[equipSlot]; - if (slot > -1) - { - itemId = Inventory[slot].ItemId; - } - } - else - { - itemId = Equipment[equipSlot]; - } - - var item = ItemBase.Get(itemId); - if (ItemBase.TryGet(itemId, out var itemDescriptor)) - { - var itemPaperdoll = Gender == 0 - ? itemDescriptor.MalePaperdoll - : itemDescriptor.FemalePaperdoll; - DrawEquipment(itemPaperdoll, item.Color * renderColor); - } - } + return; } - } + + renderColor.A /= 2; + break; } } - private int NormalSpriteAnimationFrame + if (transformedSprite != TransformedSprite) { - get - { - var frame = WalkFrame; - - if (IsBlocking) - { - frame = Options.Instance.Sprites.NormalBlockFrame; - } - else if (IsCasting) - { - frame = Options.Instance.Sprites.NormalCastFrame; - } - // Checks if the entity is attacking or not. - // Note: the calculation differs with IsAttacking because - // frames are intended to behave differently with normal sprite-sheets. - else if (AttackTimer - (CalculateAttackTime() / 2) > Timing.Global.Milliseconds) - { - frame = Options.Instance.Sprites.NormalAttackFrame; - } + TransformedSprite = transformedSprite; + } - if (frame >= SpriteFrames) - { - frame = SpriteFrames / 2; - } + //Check if there is no transformed sprite set + if (string.IsNullOrEmpty(sprite)) + { + sprite = Sprite; + Sprite = sprite; + } - return frame; - } + if (!AnimatedTextures.TryGetValue(SpriteAnimation, out var texture)) + { + texture = Texture; } - private int PickSpriteRow(Direction direction) + if (texture == default) { - switch (direction) - { - case Direction.Left: - case Direction.DownLeft when mLastDirection == Direction.Left: - case Direction.UpLeft when mLastDirection == Direction.Left: - return 1; + // We don't have a texture to render, but we still want this to be targetable. + WorldPos = new FloatRect( + map.GetX() + X * Options.TileWidth + OffsetX, + map.GetY() + Y * Options.TileHeight + OffsetY, + Options.TileWidth, + Options.TileHeight); + return; + } - case Direction.Right: - case Direction.DownRight when mLastDirection == Direction.Right: - case Direction.UpRight when mLastDirection == Direction.Right: - return 2; + var spriteRow = PickSpriteRow(Dir); - case Direction.Up: - case Direction.UpLeft when mLastDirection != Direction.Left: - case Direction.UpRight when mLastDirection != Direction.Right: - return 3; + var frameWidth = texture.GetWidth() / SpriteFrames; + var frameHeight = texture.GetHeight() / Options.Instance.Sprites.Directions; - case Direction.Down: - case Direction.DownLeft when mLastDirection != Direction.Left: - case Direction.DownRight when mLastDirection != Direction.Right: - default: - return 0; - } + var frame = SpriteFrame; + if (Options.AnimatedSprites.Contains(sprite.ToLower())) + { + frame = AnimationFrame; } - - public void PickLastDirection(Direction direction) + else if (SpriteAnimation == SpriteAnimations.Normal) { - switch (direction) - { - case Direction.Left: - case Direction.DownLeft when mLastDirection == Direction.Left: - case Direction.UpLeft when mLastDirection == Direction.Left: - mLastDirection = Direction.Left; - break; + frame = NormalSpriteAnimationFrame; + } - case Direction.Right: - case Direction.DownRight when mLastDirection == Direction.Right: - case Direction.UpRight when mLastDirection == Direction.Right: - mLastDirection = Direction.Right; - break; + var srcRectangle = new FloatRect(frame * frameWidth, spriteRow * frameHeight, frameWidth, frameHeight); + var destRectangle = new FloatRect( + (int)Math.Ceiling(Origin.X - frameWidth / 2f), + (int)Math.Ceiling(Origin.Y - frameHeight), + srcRectangle.Width, + srcRectangle.Height + ); - case Direction.Up: - case Direction.UpLeft when mLastDirection != Direction.Left: - case Direction.UpRight when mLastDirection != Direction.Right: - mLastDirection = Direction.Up; - break; + WorldPos = destRectangle; - case Direction.Down: - case Direction.DownLeft when mLastDirection != Direction.Left: - case Direction.DownRight when mLastDirection != Direction.Right: - default: - mLastDirection = Direction.Down; - break; + //Order the layers of paperdolls and sprites + for (var z = 0; z < Options.PaperdollOrder[(int)mLastDirection].Count; z++) + { + var paperdoll = Options.PaperdollOrder[(int)mLastDirection][z]; + var equipSlot = Options.EquipmentSlots.IndexOf(paperdoll); + + //Check for player + if (string.Equals("Player", paperdoll, StringComparison.Ordinal)) + { + Graphics.DrawGameTexture(texture, srcRectangle, destRectangle, renderColor); + } + else if (equipSlot > -1) + { + //Don't render the paperdolls if they have transformed. + if (sprite == Sprite && Equipment.Length == Options.EquipmentSlots.Count) + { + if (Equipment[equipSlot] != Guid.Empty && this != Globals.Me || + MyEquipment[equipSlot] < Options.MaxInvItems) + { + var itemId = Guid.Empty; + if (this == Globals.Me) + { + var slot = MyEquipment[equipSlot]; + if (slot > -1) + { + itemId = Inventory[slot].ItemId; + } + } + else + { + itemId = Equipment[equipSlot]; + } + + var item = ItemBase.Get(itemId); + if (ItemBase.TryGet(itemId, out var itemDescriptor)) + { + var itemPaperdoll = Gender == 0 + ? itemDescriptor.MalePaperdoll + : itemDescriptor.FemalePaperdoll; + DrawEquipment(itemPaperdoll, item.Color * renderColor); + } + } + } } } + } - public void DrawChatBubbles() + private int NormalSpriteAnimationFrame + { + get { - //Don't draw if the entity is hidden - if (IsHidden) + var frame = WalkFrame; + + if (IsBlocking) { - return; + frame = Options.Instance.Sprites.NormalBlockFrame; } - - //If unit is stealthed, don't render unless the entity is the player or party member. - if (!ShouldDraw) + else if (IsCasting) { - return; + frame = Options.Instance.Sprites.NormalCastFrame; + } + // Checks if the entity is attacking or not. + // Note: the calculation differs with IsAttacking because + // frames are intended to behave differently with normal sprite-sheets. + else if (AttackTimer - (CalculateAttackTime() / 2) > Timing.Global.Milliseconds) + { + frame = Options.Instance.Sprites.NormalAttackFrame; } - var chatbubbles = mChatBubbles.ToArray(); - var bubbleoffset = 0f; - for (var i = chatbubbles.Length - 1; i > -1; i--) + if (frame >= SpriteFrames) { - bubbleoffset = chatbubbles[i].Draw(bubbleoffset); + frame = SpriteFrames / 2; } + + return frame; } + } - /// - /// Draws the equipment of entities using paperdoll texture files. - /// - public virtual void DrawEquipment(string filename, Color renderColor) + private int PickSpriteRow(Direction direction) + { + switch (direction) { - // Get the current map. - var map = Maps.MapInstance.Get(MapId); + case Direction.Left: + case Direction.DownLeft when mLastDirection == Direction.Left: + case Direction.UpLeft when mLastDirection == Direction.Left: + return 1; + + case Direction.Right: + case Direction.DownRight when mLastDirection == Direction.Right: + case Direction.UpRight when mLastDirection == Direction.Right: + return 2; + + case Direction.Up: + case Direction.UpLeft when mLastDirection != Direction.Left: + case Direction.UpRight when mLastDirection != Direction.Right: + return 3; + + case Direction.Down: + case Direction.DownLeft when mLastDirection != Direction.Left: + case Direction.DownRight when mLastDirection != Direction.Right: + default: + return 0; + } + } - // If the map is null or hideEquipment is true: do nothing. - if (map == null || map.HideEquipment) - { - return; - } + public void PickLastDirection(Direction direction) + { + switch (direction) + { + case Direction.Left: + case Direction.DownLeft when mLastDirection == Direction.Left: + case Direction.UpLeft when mLastDirection == Direction.Left: + mLastDirection = Direction.Left; + break; + + case Direction.Right: + case Direction.DownRight when mLastDirection == Direction.Right: + case Direction.UpRight when mLastDirection == Direction.Right: + mLastDirection = Direction.Right; + break; + + case Direction.Up: + case Direction.UpLeft when mLastDirection != Direction.Left: + case Direction.UpRight when mLastDirection != Direction.Right: + mLastDirection = Direction.Up; + break; + + case Direction.Down: + case Direction.DownLeft when mLastDirection != Direction.Left: + case Direction.DownRight when mLastDirection != Direction.Right: + default: + mLastDirection = Direction.Down; + break; + } + } - // Paperdoll textures and Frames. - GameTexture paperdollTex = null; - var spriteFrames = SpriteFrames; + public void DrawChatBubbles() + { + //Don't draw if the entity is hidden + if (IsHidden) + { + return; + } - // Extract filename without it's extension. - var filenameNoExt = Path.GetFileNameWithoutExtension(filename); + //If unit is stealthed, don't render unless the entity is the player or party member. + if (!ShouldDraw) + { + return; + } - // Equipment's custom paperdoll texture. - if (SpriteAnimation == SpriteAnimations.Attack || - SpriteAnimation == SpriteAnimations.Cast || - SpriteAnimation == SpriteAnimations.Weapon) - { - // Extract animation name from the AnimatedTextures list. - var animationName = Path.GetFileNameWithoutExtension(AnimatedTextures[SpriteAnimation].Name); + var chatbubbles = mChatBubbles.ToArray(); + var bubbleoffset = 0f; + for (var i = chatbubbles.Length - 1; i > -1; i--) + { + bubbleoffset = chatbubbles[i].Draw(bubbleoffset); + } + } - // Extract the substring after the separator. - var separatorIndex = animationName.IndexOf('_') + 1; - var customAnimationName = animationName.Substring(separatorIndex); + /// + /// Draws the equipment of entities using paperdoll texture files. + /// + public virtual void DrawEquipment(string filename, Color renderColor) + { + // Get the current map. + var map = Maps.MapInstance.Get(MapId); - // Try to get custom paperdoll texture. - var customPaperdollTex = - Globals.ContentManager.GetTexture(TextureType.Paperdoll, - $"{filenameNoExt}_{customAnimationName}.png"); + // If the map is null or hideEquipment is true: do nothing. + if (map == null || map.HideEquipment) + { + return; + } - // If custom paperdoll texture exists, use it. - if (customPaperdollTex != null) - { - paperdollTex = customPaperdollTex; - } - } + // Paperdoll textures and Frames. + GameTexture paperdollTex = null; + var spriteFrames = SpriteFrames; - // If there's no custom paperdoll: use the paperdoll texture based on the SpriteAnimation. - if (paperdollTex == null && !string.IsNullOrEmpty($"{SpriteAnimation}")) - { - paperdollTex = Globals.ContentManager.GetTexture(TextureType.Paperdoll, - $"{filenameNoExt}_{SpriteAnimation}.png"); - } + // Extract filename without it's extension. + var filenameNoExt = Path.GetFileNameWithoutExtension(filename); - // If the paperdoll texture is still null: try to get the default texture. - if (paperdollTex == null) - { - paperdollTex = Globals.ContentManager.GetTexture(TextureType.Paperdoll, filename); - spriteFrames = Options.Instance.Sprites.NormalFrames; - } + // Equipment's custom paperdoll texture. + if (SpriteAnimation == SpriteAnimations.Attack || + SpriteAnimation == SpriteAnimations.Cast || + SpriteAnimation == SpriteAnimations.Weapon) + { + // Extract animation name from the AnimatedTextures list. + var animationName = Path.GetFileNameWithoutExtension(AnimatedTextures[SpriteAnimation].Name); - // If the paperdoll texture is null at this point: do nothing. - if (paperdollTex == null) - { - return; - } + // Extract the substring after the separator. + var separatorIndex = animationName.IndexOf('_') + 1; + var customAnimationName = animationName.Substring(separatorIndex); - // Calculate: direction, frame width and frame height. - var spriteRow = PickSpriteRow(Dir); - var frameWidth = paperdollTex.GetWidth() / spriteFrames; - var frameHeight = paperdollTex.GetHeight() / Options.Instance.Sprites.Directions; + // Try to get custom paperdoll texture. + var customPaperdollTex = + Globals.ContentManager.GetTexture(TextureType.Paperdoll, + $"{filenameNoExt}_{customAnimationName}.png"); - // Calculate: source and destination rectangles. - var frame = SpriteFrame; - if (SpriteAnimation == SpriteAnimations.Normal) + // If custom paperdoll texture exists, use it. + if (customPaperdollTex != null) { - frame = NormalSpriteAnimationFrame; + paperdollTex = customPaperdollTex; } + } + + // If there's no custom paperdoll: use the paperdoll texture based on the SpriteAnimation. + if (paperdollTex == null && !string.IsNullOrEmpty($"{SpriteAnimation}")) + { + paperdollTex = Globals.ContentManager.GetTexture(TextureType.Paperdoll, + $"{filenameNoExt}_{SpriteAnimation}.png"); + } + + // If the paperdoll texture is still null: try to get the default texture. + if (paperdollTex == null) + { + paperdollTex = Globals.ContentManager.GetTexture(TextureType.Paperdoll, filename); + spriteFrames = Options.Instance.Sprites.NormalFrames; + } + + // If the paperdoll texture is null at this point: do nothing. + if (paperdollTex == null) + { + return; + } + + // Calculate: direction, frame width and frame height. + var spriteRow = PickSpriteRow(Dir); + var frameWidth = paperdollTex.GetWidth() / spriteFrames; + var frameHeight = paperdollTex.GetHeight() / Options.Instance.Sprites.Directions; + + // Calculate: source and destination rectangles. + var frame = SpriteFrame; + if (SpriteAnimation == SpriteAnimations.Normal) + { + frame = NormalSpriteAnimationFrame; + } - var srcRectangle = new FloatRect(frame * frameWidth, spriteRow * frameHeight, frameWidth, frameHeight); - var destRectangle = new FloatRect( - (int)Math.Ceiling(Center.X - frameWidth / 2f), - (int)Math.Ceiling(Center.Y - frameHeight / 2f), - srcRectangle.Width, - srcRectangle.Height - ); + var srcRectangle = new FloatRect(frame * frameWidth, spriteRow * frameHeight, frameWidth, frameHeight); + var destRectangle = new FloatRect( + (int)Math.Ceiling(Center.X - frameWidth / 2f), + (int)Math.Ceiling(Center.Y - frameHeight / 2f), + srcRectangle.Width, + srcRectangle.Height + ); - // Draw the paperdoll texture using: source and destination rectangles along with the render color. - Graphics.DrawGameTexture(paperdollTex, srcRectangle, destRectangle, renderColor); - } + // Draw the paperdoll texture using: source and destination rectangles along with the render color. + Graphics.DrawGameTexture(paperdollTex, srcRectangle, destRectangle, renderColor); + } - protected virtual void CalculateOrigin() + protected virtual void CalculateOrigin() + { + if (LatestMap == default) { - if (LatestMap == default) - { - mOrigin = default; - return; - } - - mOrigin = new Pointf( - LatestMap.X + X * Options.TileWidth + OffsetX + Options.TileWidth / 2, - LatestMap.Y + Y * Options.TileHeight + OffsetY + Options.TileHeight - ); + mOrigin = default; + return; } - public virtual float GetTop(int overrideHeight = -1) - { - if (LatestMap == default) - { - return 0f; - } + mOrigin = new Pointf( + LatestMap.X + X * Options.TileWidth + OffsetX + Options.TileWidth / 2, + LatestMap.Y + Y * Options.TileHeight + OffsetY + Options.TileHeight + ); + } - var y = (int)Math.Ceiling(Origin.Y); + public virtual float GetTop(int overrideHeight = -1) + { + if (LatestMap == default) + { + return 0f; + } - if (overrideHeight > -1) - { - y -= overrideHeight / Options.Instance.Sprites.Directions; - } - else if (Texture != null) - { - y -= Texture.Height / Options.Instance.Sprites.Directions; - } + var y = (int)Math.Ceiling(Origin.Y); - return y; + if (overrideHeight > -1) + { + y -= overrideHeight / Options.Instance.Sprites.Directions; } - - public void DrawLabels( - string label, - int position, - Color labelColor, - Color textColor, - Color borderColor = null, - Color backgroundColor = null - ) + else if (Texture != null) { - // Are we supposed to hide this Label? - if (!ShouldDrawName || string.IsNullOrWhiteSpace(label)) - { - return; - } + y -= Texture.Height / Options.Instance.Sprites.Directions; + } - var map = MapInstance; - if (map == null) - { - return; - } + return y; + } - if (borderColor == null) - { - borderColor = Color.Transparent; - } + public void DrawLabels( + string label, + int position, + Color labelColor, + Color textColor, + Color borderColor = null, + Color backgroundColor = null + ) + { + // Are we supposed to hide this Label? + if (!ShouldDrawName || string.IsNullOrWhiteSpace(label)) + { + return; + } - if (backgroundColor == null) - { - backgroundColor = Color.Transparent; - } + var map = MapInstance; + if (map == null) + { + return; + } - //If we have a non-transparent label color then use it, otherwise use the players name color - if (labelColor != null && labelColor.A != 0) - { - textColor = labelColor; - } + if (borderColor == null) + { + borderColor = Color.Transparent; + } - var textSize = Graphics.Renderer.MeasureText(label, Graphics.EntityNameFont, 1); + if (backgroundColor == null) + { + backgroundColor = Color.Transparent; + } - var x = (int)Math.Ceiling(Origin.X); - var y = position == 0 ? GetLabelLocation(LabelType.Header) : GetLabelLocation(LabelType.Footer); + //If we have a non-transparent label color then use it, otherwise use the players name color + if (labelColor != null && labelColor.A != 0) + { + textColor = labelColor; + } - if (backgroundColor != Color.Transparent) - { - Graphics.DrawGameTexture( - Graphics.Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), - new FloatRect(x - textSize.X / 2f - 4, y, textSize.X + 8, textSize.Y), backgroundColor - ); - } + var textSize = Graphics.Renderer.MeasureText(label, Graphics.EntityNameFont, 1); - Graphics.Renderer.DrawString( - label, Graphics.EntityNameFont, x - (int)Math.Ceiling(textSize.X / 2f), (int)y, 1, - Color.FromArgb(textColor.ToArgb()), true, null, Color.FromArgb(borderColor.ToArgb()) + var x = (int)Math.Ceiling(Origin.X); + var y = position == 0 ? GetLabelLocation(LabelType.Header) : GetLabelLocation(LabelType.Footer); + + if (backgroundColor != Color.Transparent) + { + Graphics.DrawGameTexture( + Graphics.Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), + new FloatRect(x - textSize.X / 2f - 4, y, textSize.X + 8, textSize.Y), backgroundColor ); } - public virtual void DrawName(Color textColor, Color borderColor = null, Color backgroundColor = null) + Graphics.Renderer.DrawString( + label, Graphics.EntityNameFont, x - (int)Math.Ceiling(textSize.X / 2f), (int)y, 1, + Color.FromArgb(textColor.ToArgb()), true, null, Color.FromArgb(borderColor.ToArgb()) + ); + } + + public virtual void DrawName(Color textColor, Color borderColor = null, Color backgroundColor = null) + { + // Are we really supposed to draw this name? + if (!ShouldDrawName) { - // Are we really supposed to draw this name? - if (!ShouldDrawName) - { - return; - } + return; + } - //Check for npc colors - if (textColor == null) + //Check for npc colors + if (textColor == null) + { + LabelColor? color; + switch (Aggression) { - LabelColor? color; - switch (Aggression) - { - case NpcAggression.Aggressive: - color = CustomColors.Names.Npcs["Aggressive"]; - break; - - case NpcAggression.AttackWhenAttacked: - color = CustomColors.Names.Npcs["AttackWhenAttacked"]; - break; + case NpcAggression.Aggressive: + color = CustomColors.Names.Npcs["Aggressive"]; + break; - case NpcAggression.AttackOnSight: - color = CustomColors.Names.Npcs["AttackOnSight"]; - break; + case NpcAggression.AttackWhenAttacked: + color = CustomColors.Names.Npcs["AttackWhenAttacked"]; + break; - case NpcAggression.Guard: - color = CustomColors.Names.Npcs["Guard"]; - break; + case NpcAggression.AttackOnSight: + color = CustomColors.Names.Npcs["AttackOnSight"]; + break; - case NpcAggression.Neutral: - default: - color = CustomColors.Names.Npcs["Neutral"]; - break; - } + case NpcAggression.Guard: + color = CustomColors.Names.Npcs["Guard"]; + break; - if (color != null) - { - textColor = color?.Name; - backgroundColor = backgroundColor ?? color?.Background; - borderColor = borderColor ?? color?.Outline; - } + case NpcAggression.Neutral: + default: + color = CustomColors.Names.Npcs["Neutral"]; + break; } - if (borderColor == null) + if (color != null) { - borderColor = Color.Transparent; + textColor = color?.Name; + backgroundColor = backgroundColor ?? color?.Background; + borderColor = borderColor ?? color?.Outline; } + } - if (backgroundColor == null) - { - backgroundColor = Color.Transparent; - } + if (borderColor == null) + { + borderColor = Color.Transparent; + } - var name = Name; - if ((this is Player && Options.Player.ShowLevelByName) || (Type == EntityType.GlobalEntity && Options.Npc.ShowLevelByName)) - { - name = Strings.GameWindow.EntityNameAndLevel.ToString(Name, Level); - } + if (backgroundColor == null) + { + backgroundColor = Color.Transparent; + } - var textSize = Graphics.Renderer.MeasureText(name, Graphics.EntityNameFont, 1); + var name = Name; + if ((this is Player && Options.Player.ShowLevelByName) || (Type == EntityType.GlobalEntity && Options.Npc.ShowLevelByName)) + { + name = Strings.GameWindow.EntityNameAndLevel.ToString(Name, Level); + } - var x = (int)Math.Ceiling(Origin.X); - var y = GetLabelLocation(LabelType.Name); + var textSize = Graphics.Renderer.MeasureText(name, Graphics.EntityNameFont, 1); - if (backgroundColor != Color.Transparent) - { - Graphics.DrawGameTexture( - Graphics.Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), - new FloatRect(x - textSize.X / 2f - 4, y, textSize.X + 8, textSize.Y), backgroundColor - ); - } + var x = (int)Math.Ceiling(Origin.X); + var y = GetLabelLocation(LabelType.Name); - Graphics.Renderer.DrawString( - name, Graphics.EntityNameFont, x - (int)Math.Ceiling(textSize.X / 2f), (int)y, 1, - Color.FromArgb(textColor.ToArgb()), true, null, Color.FromArgb(borderColor.ToArgb()) + if (backgroundColor != Color.Transparent) + { + Graphics.DrawGameTexture( + Graphics.Renderer.GetWhiteTexture(), new FloatRect(0, 0, 1, 1), + new FloatRect(x - textSize.X / 2f - 4, y, textSize.X + 8, textSize.Y), backgroundColor ); } - public float GetLabelLocation(LabelType type) - { - var y = GetTop() - 8; + Graphics.Renderer.DrawString( + name, Graphics.EntityNameFont, x - (int)Math.Ceiling(textSize.X / 2f), (int)y, 1, + Color.FromArgb(textColor.ToArgb()), true, null, Color.FromArgb(borderColor.ToArgb()) + ); + } - //Need room for HP bar if not an event. - if (!(this is Event) && ShouldDrawHpBar) - { - y -= GetBoundingHpBarTexture().Height + 2; - } + public float GetLabelLocation(LabelType type) + { + var y = GetTop() - 8; - switch (type) - { - case LabelType.Header: - y = GetLabelLocation(LabelType.Name); + //Need room for HP bar if not an event. + if (!(this is Event) && ShouldDrawHpBar) + { + y -= GetBoundingHpBarTexture().Height + 2; + } - if (string.IsNullOrWhiteSpace(HeaderLabel.Text)) - { - break; - } + switch (type) + { + case LabelType.Header: + y = GetLabelLocation(LabelType.Name); - var headerSize = Graphics.Renderer.MeasureText(HeaderLabel.Text, Graphics.EntityNameFont, 1); - y -= headerSize.Y + 2; + if (string.IsNullOrWhiteSpace(HeaderLabel.Text)) + { break; + } - case LabelType.Footer: - if (string.IsNullOrWhiteSpace(FooterLabel.Text)) - { - break; - } + var headerSize = Graphics.Renderer.MeasureText(HeaderLabel.Text, Graphics.EntityNameFont, 1); + y -= headerSize.Y + 2; + break; - var footerSize = Graphics.Renderer.MeasureText(FooterLabel.Text, Graphics.EntityNameFont, 1); - y -= footerSize.Y - 6; + case LabelType.Footer: + if (string.IsNullOrWhiteSpace(FooterLabel.Text)) + { break; + } - case LabelType.Name: - y = GetLabelLocation(LabelType.Footer); - var nameSize = Graphics.Renderer.MeasureText(Name, Graphics.EntityNameFont, 1); - y -= nameSize.Y + (string.IsNullOrEmpty(FooterLabel.Text) ? -6 : 2); - break; + var footerSize = Graphics.Renderer.MeasureText(FooterLabel.Text, Graphics.EntityNameFont, 1); + y -= footerSize.Y - 6; + break; - case LabelType.ChatBubble: - y = GetLabelLocation(LabelType.Guild) - 2; - break; + case LabelType.Name: + y = GetLabelLocation(LabelType.Footer); + var nameSize = Graphics.Renderer.MeasureText(Name, Graphics.EntityNameFont, 1); + y -= nameSize.Y + (string.IsNullOrEmpty(FooterLabel.Text) ? -6 : 2); + break; - case LabelType.Guild: - if (this is Player player) - { - // Do we have a header? If so, slightly change the position! - if (string.IsNullOrWhiteSpace(HeaderLabel.Text)) - { - y = GetLabelLocation(LabelType.Name); - } - else - { - y = GetLabelLocation(LabelType.Header); - } + case LabelType.ChatBubble: + y = GetLabelLocation(LabelType.Guild) - 2; + break; - if (string.IsNullOrWhiteSpace(player.Guild)) - { - break; - } + case LabelType.Guild: + if (this is Player player) + { + // Do we have a header? If so, slightly change the position! + if (string.IsNullOrWhiteSpace(HeaderLabel.Text)) + { + y = GetLabelLocation(LabelType.Name); + } + else + { + y = GetLabelLocation(LabelType.Header); + } - var guildSize = Graphics.Renderer.MeasureText(player.Guild, Graphics.EntityNameFont, 1); - y -= 2 + guildSize.Y; + if (string.IsNullOrWhiteSpace(player.Guild)) + { + break; } - break; - } - return y; + var guildSize = Graphics.Renderer.MeasureText(player.Guild, Graphics.EntityNameFont, 1); + y -= 2 + guildSize.Y; + } + break; } - public long GetShieldSize() + return y; + } + + public long GetShieldSize() + { + long shieldSize = 0; + foreach (var status in Status) { - long shieldSize = 0; - foreach (var status in Status) + if (status.Type == SpellEffect.Shield) { - if (status.Type == SpellEffect.Shield) - { - shieldSize += status.Shield[(int)Enums.Vital.Health]; - } + shieldSize += status.Shield[(int)Enums.Vital.Health]; } - return shieldSize; } + return shieldSize; + } - protected virtual bool ShouldDrawHpBar + protected virtual bool ShouldDrawHpBar + { + get { - get + if (ShouldNotDrawHpBar) { - if (ShouldNotDrawHpBar) - { - return false; - } - - if (IsHovered) - { - return true; - } - - if (GetShieldSize() > 0) - { - return true; - } + return false; + } - if (Vital[(int)Enums.Vital.Health] != MaxVital[(int)Enums.Vital.Health]) - { - return true; - } + if (IsHovered) + { + return true; + } - return GetType() == typeof(Entity) && Globals.Database.NpcOverheadHpBar; + if (GetShieldSize() > 0) + { + return true; } - } - protected bool ShouldNotDrawHpBar - { - get + if (Vital[(int)Enums.Vital.Health] != MaxVital[(int)Enums.Vital.Health]) { - return LatestMap == default || !ShouldDraw || Vital[(int)Enums.Vital.Health] < 1; + return true; } + + return GetType() == typeof(Entity) && Globals.Database.NpcOverheadHpBar; } + } - public GameTexture GetBoundingHpBarTexture() + protected bool ShouldNotDrawHpBar + { + get { - return GameTexture.GetBoundingTexture( - BoundsComparison.Height, - Globals.ContentManager.GetTexture(TextureType.Misc, "hpbackground.png"), - Globals.ContentManager.GetTexture(TextureType.Misc, "hpbar.png"), - Globals.ContentManager.GetTexture(TextureType.Misc, "shieldbar.png") - ); + return LatestMap == default || !ShouldDraw || Vital[(int)Enums.Vital.Health] < 1; } + } + + public GameTexture GetBoundingHpBarTexture() + { + return GameTexture.GetBoundingTexture( + BoundsComparison.Height, + Globals.ContentManager.GetTexture(TextureType.Misc, "hpbackground.png"), + Globals.ContentManager.GetTexture(TextureType.Misc, "hpbar.png"), + Globals.ContentManager.GetTexture(TextureType.Misc, "shieldbar.png") + ); + } - public void DrawHpBar() + public void DrawHpBar() + { + // Are we supposed to hide this HP bar? + if (!ShouldDrawHpBar) { - // Are we supposed to hide this HP bar? - if (!ShouldDrawHpBar) - { - return; - } + return; + } - var hpBackground = Globals.ContentManager.GetTexture(TextureType.Misc, "hpbackground.png"); - var hpForeground = Globals.ContentManager.GetTexture(TextureType.Misc, "hpbar.png"); - var shieldForeground = Globals.ContentManager.GetTexture(TextureType.Misc, "shieldbar.png"); + var hpBackground = Globals.ContentManager.GetTexture(TextureType.Misc, "hpbackground.png"); + var hpForeground = Globals.ContentManager.GetTexture(TextureType.Misc, "hpbar.png"); + var shieldForeground = Globals.ContentManager.GetTexture(TextureType.Misc, "shieldbar.png"); - var boundingTeture = GameTexture.GetBoundingTexture( - BoundsComparison.Height, - hpBackground, - hpForeground, - shieldForeground - ); + var boundingTeture = GameTexture.GetBoundingTexture( + BoundsComparison.Height, + hpBackground, + hpForeground, + shieldForeground + ); - var foregroundBoundingTexture = hpForeground; + var foregroundBoundingTexture = hpForeground; - // Check for shields - var maxVital = MaxVital[(int)Enums.Vital.Health]; - var shieldSize = GetShieldSize(); + // Check for shields + var maxVital = MaxVital[(int)Enums.Vital.Health]; + var shieldSize = GetShieldSize(); - if (shieldSize + Vital[(int)Enums.Vital.Health] > maxVital) - { - maxVital = shieldSize + Vital[(int)Enums.Vital.Health]; - } + if (shieldSize + Vital[(int)Enums.Vital.Health] > maxVital) + { + maxVital = shieldSize + Vital[(int)Enums.Vital.Health]; + } - var hpfillRatio = (float)Vital[(int)Enums.Vital.Health] / maxVital; - hpfillRatio = Math.Min(1, Math.Max(0, hpfillRatio)); + var hpfillRatio = (float)Vital[(int)Enums.Vital.Health] / maxVital; + hpfillRatio = Math.Min(1, Math.Max(0, hpfillRatio)); - var hpFillWidth = (int)Math.Round(hpfillRatio * foregroundBoundingTexture.Width); - var shieldPixelFillRatio = (foregroundBoundingTexture.Width - hpFillWidth) / ((float)foregroundBoundingTexture.Width); - var shieldFillWidth = (int)Math.Floor(foregroundBoundingTexture.Width * shieldPixelFillRatio); + var hpFillWidth = (int)Math.Round(hpfillRatio * foregroundBoundingTexture.Width); + var shieldPixelFillRatio = (foregroundBoundingTexture.Width - hpFillWidth) / ((float)foregroundBoundingTexture.Width); + var shieldFillWidth = (int)Math.Floor(foregroundBoundingTexture.Width * shieldPixelFillRatio); - if (foregroundBoundingTexture.Width < hpFillWidth + shieldFillWidth) - { - hpFillWidth = Math.Max(1, foregroundBoundingTexture.Width - shieldFillWidth); - shieldFillWidth = Math.Max(1, foregroundBoundingTexture.Width - hpFillWidth); - } + if (foregroundBoundingTexture.Width < hpFillWidth + shieldFillWidth) + { + hpFillWidth = Math.Max(1, foregroundBoundingTexture.Width - shieldFillWidth); + shieldFillWidth = Math.Max(1, foregroundBoundingTexture.Width - hpFillWidth); + } - if (shieldSize > 0 && shieldFillWidth < 1) - { - hpFillWidth -= 1 - shieldFillWidth; - shieldFillWidth = 1; - } + if (shieldSize > 0 && shieldFillWidth < 1) + { + hpFillWidth -= 1 - shieldFillWidth; + shieldFillWidth = 1; + } - var x = (int)Math.Ceiling(Origin.X); - var y = (int)Math.Ceiling(Origin.Y); + var x = (int)Math.Ceiling(Origin.X); + var y = (int)Math.Ceiling(Origin.Y); - var sprite = Globals.ContentManager.GetTexture(TextureType.Entity, Sprite); - if (sprite != null) - { - y -= sprite.Height / Options.Instance.Sprites.Directions; - y -= boundingTeture.Height + 2; - } + var sprite = Globals.ContentManager.GetTexture(TextureType.Entity, Sprite); + if (sprite != null) + { + y -= sprite.Height / Options.Instance.Sprites.Directions; + y -= boundingTeture.Height + 2; + } - y += boundingTeture.Height / 2; + y += boundingTeture.Height / 2; - if (hpBackground != null) - { - Graphics.DrawGameTexture( - hpBackground, new FloatRect(0, 0, hpBackground.Width, hpBackground.Height), - new FloatRect(x - hpBackground.Width / 2, y - hpBackground.Height / 2, hpBackground.Width, hpBackground.Height), Color.White - ); - } + if (hpBackground != null) + { + Graphics.DrawGameTexture( + hpBackground, new FloatRect(0, 0, hpBackground.Width, hpBackground.Height), + new FloatRect(x - hpBackground.Width / 2, y - hpBackground.Height / 2, hpBackground.Width, hpBackground.Height), Color.White + ); + } - if (hpForeground != null) - { - Graphics.DrawGameTexture( - hpForeground, - new FloatRect(0, 0, hpFillWidth, hpForeground.Height), - new FloatRect(x - foregroundBoundingTexture.Width / 2, y - hpForeground.Height / 2, hpFillWidth, hpForeground.Height), Color.White - ); - } + if (hpForeground != null) + { + Graphics.DrawGameTexture( + hpForeground, + new FloatRect(0, 0, hpFillWidth, hpForeground.Height), + new FloatRect(x - foregroundBoundingTexture.Width / 2, y - hpForeground.Height / 2, hpFillWidth, hpForeground.Height), Color.White + ); + } - if (shieldSize > 0 && shieldForeground != null) //Check for a shield to render - { - var shieldFillRatio = shieldFillWidth / (float)foregroundBoundingTexture.Width; - Graphics.DrawGameTexture( - shieldForeground, - new FloatRect(shieldForeground.Width * (1 - shieldFillRatio), 0, shieldForeground.Width * shieldFillRatio, shieldForeground.Height), - new FloatRect(x - foregroundBoundingTexture.Width / 2 + hpFillWidth, y - shieldForeground.Height / 2, shieldFillWidth, shieldForeground.Height), Color.White - ); - } + if (shieldSize > 0 && shieldForeground != null) //Check for a shield to render + { + var shieldFillRatio = shieldFillWidth / (float)foregroundBoundingTexture.Width; + Graphics.DrawGameTexture( + shieldForeground, + new FloatRect(shieldForeground.Width * (1 - shieldFillRatio), 0, shieldForeground.Width * shieldFillRatio, shieldForeground.Height), + new FloatRect(x - foregroundBoundingTexture.Width / 2 + hpFillWidth, y - shieldForeground.Height / 2, shieldFillWidth, shieldForeground.Height), Color.White + ); } + } - public bool ShouldDrawCastingBar => ShouldDraw && IsCasting && LatestMap != default; + public bool ShouldDrawCastingBar => ShouldDraw && IsCasting && LatestMap != default; - public void DrawCastingBar() + public void DrawCastingBar() + { + // Are we supposed to hide this cast bar? + if (!ShouldDrawCastingBar) { - // Are we supposed to hide this cast bar? - if (!ShouldDrawCastingBar) - { - return; - } + return; + } - var castingSpell = SpellBase.Get(SpellCast); - if (castingSpell == null) - { - return; - } + var castingSpell = SpellBase.Get(SpellCast); + if (castingSpell == null) + { + return; + } - var castBackground = Globals.ContentManager.GetTexture(TextureType.Misc, "castbackground.png"); - var castForeground = Globals.ContentManager.GetTexture(TextureType.Misc, "castbar.png"); - var boundingTexture = GameTexture.GetBoundingTexture(BoundsComparison.Height, castBackground, castForeground); + var castBackground = Globals.ContentManager.GetTexture(TextureType.Misc, "castbackground.png"); + var castForeground = Globals.ContentManager.GetTexture(TextureType.Misc, "castbar.png"); + var boundingTexture = GameTexture.GetBoundingTexture(BoundsComparison.Height, castBackground, castForeground); - float remainingTime = CastTime - Timing.Global.Milliseconds; - var fillRatio = 1 - remainingTime / castingSpell.CastDuration; + float remainingTime = CastTime - Timing.Global.Milliseconds; + var fillRatio = 1 - remainingTime / castingSpell.CastDuration; - var x = (int)Math.Ceiling(Origin.X); - var y = (int)Math.Ceiling(Origin.Y); + var x = (int)Math.Ceiling(Origin.X); + var y = (int)Math.Ceiling(Origin.Y); - y += 2 + boundingTexture.Height / 2; + y += 2 + boundingTexture.Height / 2; - if (castBackground != null) - { - Graphics.DrawGameTexture( - castBackground, new FloatRect(0, 0, castBackground.Width, castBackground.Height), - new FloatRect(x - castBackground.Width / 2, y - castBackground.Height / 2, castBackground.Width, castBackground.Height), Color.White - ); - } + if (castBackground != null) + { + Graphics.DrawGameTexture( + castBackground, new FloatRect(0, 0, castBackground.Width, castBackground.Height), + new FloatRect(x - castBackground.Width / 2, y - castBackground.Height / 2, castBackground.Width, castBackground.Height), Color.White + ); + } - if (castForeground != null) - { - Graphics.DrawGameTexture( - castForeground, - new FloatRect(0, 0, castForeground.GetWidth() * fillRatio, castForeground.Height), - new FloatRect(x - castForeground.Width / 2, y - castForeground.Height / 2, castForeground.Width * fillRatio, castForeground.Height), Color.White - ); - } + if (castForeground != null) + { + Graphics.DrawGameTexture( + castForeground, + new FloatRect(0, 0, castForeground.GetWidth() * fillRatio, castForeground.Height), + new FloatRect(x - castForeground.Width / 2, y - castForeground.Height / 2, castForeground.Width * fillRatio, castForeground.Height), Color.White + ); } + } - public bool ShouldDrawTarget => !(this is Projectile) && LatestMap != default; + public bool ShouldDrawTarget => !(this is Projectile) && LatestMap != default; - public void DrawTarget(int priority) + public void DrawTarget(int priority) + { + // Should we draw the target? + if (!ShouldDrawTarget) { - // Should we draw the target? - if (!ShouldDrawTarget) - { - return; - } + return; + } - var targetTexture = Globals.ContentManager.GetTexture(TextureType.Misc, "target.png"); - if (targetTexture == null) - { - return; - } + var targetTexture = Globals.ContentManager.GetTexture(TextureType.Misc, "target.png"); + if (targetTexture == null) + { + return; + } - var srcRectangle = new FloatRect( - priority * targetTexture.GetWidth() / 2f, - 0, - targetTexture.GetWidth() / 2f, - targetTexture.GetHeight() - ); + var srcRectangle = new FloatRect( + priority * targetTexture.GetWidth() / 2f, + 0, + targetTexture.GetWidth() / 2f, + targetTexture.GetHeight() + ); + + var destRectangle = new FloatRect( + (float)Math.Ceiling(WorldPos.X + (WorldPos.Width - targetTexture.GetWidth() / 2) / 2), + (float)Math.Ceiling(WorldPos.Y + (WorldPos.Height - targetTexture.GetHeight()) / 2), + srcRectangle.Width, + srcRectangle.Height + ); + + Graphics.DrawGameTexture(targetTexture, srcRectangle, destRectangle, Color.White); + } - var destRectangle = new FloatRect( - (float)Math.Ceiling(WorldPos.X + (WorldPos.Width - targetTexture.GetWidth() / 2) / 2), - (float)Math.Ceiling(WorldPos.Y + (WorldPos.Height - targetTexture.GetHeight()) / 2), - srcRectangle.Width, - srcRectangle.Height - ); + public virtual bool CanBeAttacked => true; - Graphics.DrawGameTexture(targetTexture, srcRectangle, destRectangle, Color.White); + //Chatting + public void AddChatBubble(string text) + { + if (string.IsNullOrEmpty(text)) + { + return; } - public virtual bool CanBeAttacked => true; + mChatBubbles.Add(new ChatBubble(this, text)); + } - //Chatting - public void AddChatBubble(string text) + //Statuses + public bool StatusActive(Guid guid) + { + foreach (var status in Status) { - if (string.IsNullOrEmpty(text)) + if (status.SpellId == guid && status.IsActive) { - return; + return true; } - - mChatBubbles.Add(new ChatBubble(this, text)); } - //Statuses - public bool StatusActive(Guid guid) + return false; + } + + public IStatus GetStatus(Guid guid) + { + foreach (var status in Status) { - foreach (var status in Status) + if (status.SpellId == guid && status.IsActive) { - if (status.SpellId == guid && status.IsActive) - { - return true; - } + return status; } - - return false; } - public IStatus GetStatus(Guid guid) + return null; + } + + public void SortStatuses() + { + //Sort Status effects by remaining time + Status = Status.OrderByDescending(x => x.RemainingMs).ToList(); + } + + private void UpdateSpriteAnimation() + { + //Exit if textures haven't been loaded yet + if (AnimatedTextures.Count == 0) { - foreach (var status in Status) - { - if (status.SpellId == guid && status.IsActive) - { - return status; - } - } + return; + } + + var timingMilliseconds = Timing.Global.Milliseconds; + var isNotBlockingAndCasting = !IsBlocking && !IsCasting; - return null; + SpriteAnimation = SpriteAnimations.Normal; + if (AnimatedTextures.TryGetValue(SpriteAnimations.Idle, out _) && + LastActionTime + Options.Instance.Sprites.IdleStartDelay < timingMilliseconds && + isNotBlockingAndCasting) + { + SpriteAnimation = SpriteAnimations.Idle; } - public void SortStatuses() + if (IsMoving && !IsAttacking && isNotBlockingAndCasting) { - //Sort Status effects by remaining time - Status = Status.OrderByDescending(x => x.RemainingMs).ToList(); + SpriteAnimation = SpriteAnimations.Normal; + LastActionTime = timingMilliseconds; } - private void UpdateSpriteAnimation() + if (IsAttacking && isNotBlockingAndCasting) { - //Exit if textures haven't been loaded yet - if (AnimatedTextures.Count == 0) + // Normal sprite-sheets has their own handler for attacking frames. + if (AnimatedTextures.TryGetValue(SpriteAnimations.Normal, out _)) { return; } - var timingMilliseconds = Timing.Global.Milliseconds; - var isNotBlockingAndCasting = !IsBlocking && !IsCasting; - - SpriteAnimation = SpriteAnimations.Normal; - if (AnimatedTextures.TryGetValue(SpriteAnimations.Idle, out _) && - LastActionTime + Options.Instance.Sprites.IdleStartDelay < timingMilliseconds && - isNotBlockingAndCasting) - { - SpriteAnimation = SpriteAnimations.Idle; - } + var timeInAttack = CalculateAttackTime() - (AttackTimer - timingMilliseconds); + LastActionTime = Timing.Global.Milliseconds; - if (IsMoving && !IsAttacking && isNotBlockingAndCasting) + if (AnimatedTextures.TryGetValue(SpriteAnimations.Attack, out _)) { - SpriteAnimation = SpriteAnimations.Normal; - LastActionTime = timingMilliseconds; + SpriteAnimation = SpriteAnimations.Attack; } - if (IsAttacking && isNotBlockingAndCasting) + if (Options.WeaponIndex > -1 && Options.WeaponIndex < Equipment.Length) { - // Normal sprite-sheets has their own handler for attacking frames. - if (AnimatedTextures.TryGetValue(SpriteAnimations.Normal, out _)) - { - return; - } - - var timeInAttack = CalculateAttackTime() - (AttackTimer - timingMilliseconds); - LastActionTime = Timing.Global.Milliseconds; - - if (AnimatedTextures.TryGetValue(SpriteAnimations.Attack, out _)) - { - SpriteAnimation = SpriteAnimations.Attack; - } - - if (Options.WeaponIndex > -1 && Options.WeaponIndex < Equipment.Length) + if (Equipment[Options.WeaponIndex] != Guid.Empty && this != Globals.Me || + MyEquipment[Options.WeaponIndex] < Options.MaxInvItems) { - if (Equipment[Options.WeaponIndex] != Guid.Empty && this != Globals.Me || - MyEquipment[Options.WeaponIndex] < Options.MaxInvItems) + var itemId = Guid.Empty; + if (this == Globals.Me) { - var itemId = Guid.Empty; - if (this == Globals.Me) - { - var slot = MyEquipment[Options.WeaponIndex]; - if (slot > -1) - { - itemId = Inventory[slot].ItemId; - } - } - else - { - itemId = Equipment[Options.WeaponIndex]; - } - - var item = ItemBase.Get(itemId); - if (item != null) + var slot = MyEquipment[Options.WeaponIndex]; + if (slot > -1) { - if (AnimatedTextures.TryGetValue(SpriteAnimations.Weapon, out _)) - { - SpriteAnimation = SpriteAnimations.Weapon; - } - - if (AnimatedTextures.TryGetValue(SpriteAnimations.Shoot, out _) && - item.ProjectileId != Guid.Empty && - item.WeaponSpriteOverride == null) - { - SpriteAnimation = SpriteAnimations.Shoot; - } + itemId = Inventory[slot].ItemId; } } - } - - switch (SpriteAnimation) - { - case SpriteAnimations.Cast: - case SpriteAnimations.Idle: - case SpriteAnimations.Normal: - break; - case SpriteAnimations.Attack: - case SpriteAnimations.Shoot: - case SpriteAnimations.Weapon: - default: - SpriteFrame = (int)Math.Floor((timeInAttack / (CalculateAttackTime() / (float)SpriteFrames))); - break; - } - } - - if (IsCasting) - { - var spell = SpellBase.Get(SpellCast); - if (spell != null) - { - var duration = spell.CastDuration; - var timeInCast = duration - (CastTime - timingMilliseconds); - - // Normal sprite-sheets has their own handler for attacking frames. - if (AnimatedTextures.TryGetValue(SpriteAnimations.Cast, out _)) + else { - SpriteAnimation = SpriteAnimations.Cast; + itemId = Equipment[Options.WeaponIndex]; } - if (spell.SpellType == SpellType.CombatSpell && - spell.Combat.TargetType == SpellTargetType.Projectile && - spell.CastSpriteOverride == null) + var item = ItemBase.Get(itemId); + if (item != null) { - if (AnimatedTextures.TryGetValue(SpriteAnimations.Shoot, out _)) + if (AnimatedTextures.TryGetValue(SpriteAnimations.Weapon, out _)) + { + SpriteAnimation = SpriteAnimations.Weapon; + } + + if (AnimatedTextures.TryGetValue(SpriteAnimations.Shoot, out _) && + item.ProjectileId != Guid.Empty && + item.WeaponSpriteOverride == null) { SpriteAnimation = SpriteAnimations.Shoot; } } - - SpriteFrame = (int)Math.Floor((timeInCast / (duration / (float)SpriteFrames))); } - - LastActionTime = timingMilliseconds; } - if (SpriteAnimation == SpriteAnimations.Normal) + switch (SpriteAnimation) { - ResetSpriteFrame(); + case SpriteAnimations.Cast: + case SpriteAnimations.Idle: + case SpriteAnimations.Normal: + break; + case SpriteAnimations.Attack: + case SpriteAnimations.Shoot: + case SpriteAnimations.Weapon: + default: + SpriteFrame = (int)Math.Floor((timeInAttack / (CalculateAttackTime() / (float)SpriteFrames))); + break; } - else if (SpriteAnimation == SpriteAnimations.Idle) + } + + if (IsCasting) + { + var spell = SpellBase.Get(SpellCast); + if (spell != null) { - if (SpriteFrameTimer + Options.Instance.Sprites.IdleFrameDuration < timingMilliseconds) + var duration = spell.CastDuration; + var timeInCast = duration - (CastTime - timingMilliseconds); + + // Normal sprite-sheets has their own handler for attacking frames. + if (AnimatedTextures.TryGetValue(SpriteAnimations.Cast, out _)) + { + SpriteAnimation = SpriteAnimations.Cast; + } + + if (spell.SpellType == SpellType.CombatSpell && + spell.Combat.TargetType == SpellTargetType.Projectile && + spell.CastSpriteOverride == null) { - SpriteFrame++; - if (SpriteFrame >= SpriteFrames) + if (AnimatedTextures.TryGetValue(SpriteAnimations.Shoot, out _)) { - SpriteFrame = 0; + SpriteAnimation = SpriteAnimations.Shoot; } - - SpriteFrameTimer = timingMilliseconds; } + + SpriteFrame = (int)Math.Floor((timeInCast / (duration / (float)SpriteFrames))); } + + LastActionTime = timingMilliseconds; } - public void ResetSpriteFrame() + if (SpriteAnimation == SpriteAnimations.Normal) { - SpriteFrame = 0; - SpriteFrameTimer = 0; + ResetSpriteFrame(); } - - public virtual void LoadTextures(string textureName) + else if (SpriteAnimation == SpriteAnimations.Idle) { - AnimatedTextures.Clear(); - foreach (SpriteAnimations spriteAnimation in Enum.GetValues(typeof(SpriteAnimations))) + if (SpriteFrameTimer + Options.Instance.Sprites.IdleFrameDuration < timingMilliseconds) { - if (spriteAnimation == SpriteAnimations.Normal) + SpriteFrame++; + if (SpriteFrame >= SpriteFrames) { - Texture = Globals.ContentManager.GetTexture(TextureType.Entity, textureName); - } - else - { - LoadAnimationTexture(textureName, spriteAnimation); + SpriteFrame = 0; } + + SpriteFrameTimer = timingMilliseconds; } } + } - protected virtual void LoadAnimationTexture(string textureName, SpriteAnimations spriteAnimation) - { - SpriteAnimations spriteAnimationOveride = spriteAnimation; - string textureOverride = default; + public void ResetSpriteFrame() + { + SpriteFrame = 0; + SpriteFrameTimer = 0; + } - switch (spriteAnimation) + public virtual void LoadTextures(string textureName) + { + AnimatedTextures.Clear(); + foreach (SpriteAnimations spriteAnimation in Enum.GetValues(typeof(SpriteAnimations))) + { + if (spriteAnimation == SpriteAnimations.Normal) + { + Texture = Globals.ContentManager.GetTexture(TextureType.Entity, textureName); + } + else { - // No override for this - case SpriteAnimations.Normal: break; + LoadAnimationTexture(textureName, spriteAnimation); + } + } + } - case SpriteAnimations.Idle: break; - case SpriteAnimations.Attack: - if (this is Player player && ClassBase.TryGet(player.Class, out var classDescriptor)) + protected virtual void LoadAnimationTexture(string textureName, SpriteAnimations spriteAnimation) + { + SpriteAnimations spriteAnimationOveride = spriteAnimation; + string textureOverride = default; + + switch (spriteAnimation) + { + // No override for this + case SpriteAnimations.Normal: break; + + case SpriteAnimations.Idle: break; + case SpriteAnimations.Attack: + if (this is Player player && ClassBase.TryGet(player.Class, out var classDescriptor)) + { + textureOverride = classDescriptor.AttackSpriteOverride; + } + break; + + case SpriteAnimations.Shoot: + { + if (Equipment.Length <= Options.WeaponIndex) { - textureOverride = classDescriptor.AttackSpriteOverride; + break; } - break; - case SpriteAnimations.Shoot: + var weaponId = Equipment[Options.WeaponIndex]; + if (ItemBase.TryGet(weaponId, out var itemDescriptor)) { - if (Equipment.Length <= Options.WeaponIndex) - { - break; - } - - var weaponId = Equipment[Options.WeaponIndex]; - if (ItemBase.TryGet(weaponId, out var itemDescriptor)) - { - textureOverride = itemDescriptor.WeaponSpriteOverride; - } - - if (!string.IsNullOrWhiteSpace(textureOverride)) - { - spriteAnimationOveride = SpriteAnimations.Weapon; - } + textureOverride = itemDescriptor.WeaponSpriteOverride; } - break; - case SpriteAnimations.Cast: - if (SpellBase.TryGet(SpellCast, out var spellDescriptor)) + if (!string.IsNullOrWhiteSpace(textureOverride)) { - textureOverride = spellDescriptor.CastSpriteOverride; + spriteAnimationOveride = SpriteAnimations.Weapon; } - break; + } + break; - case SpriteAnimations.Weapon: + case SpriteAnimations.Cast: + if (SpellBase.TryGet(SpellCast, out var spellDescriptor)) + { + textureOverride = spellDescriptor.CastSpriteOverride; + } + break; + + case SpriteAnimations.Weapon: + { + if (Equipment.Length <= Options.WeaponIndex) { - if (Equipment.Length <= Options.WeaponIndex) - { - break; - } + break; + } - var weaponId = Equipment[Options.WeaponIndex]; - if (ItemBase.TryGet(weaponId, out var itemDescriptor)) - { - textureOverride = itemDescriptor.WeaponSpriteOverride; - } + var weaponId = Equipment[Options.WeaponIndex]; + if (ItemBase.TryGet(weaponId, out var itemDescriptor)) + { + textureOverride = itemDescriptor.WeaponSpriteOverride; } - break; + } + break; - default: - throw new ArgumentOutOfRangeException(nameof(spriteAnimation)); - } + default: + throw new ArgumentOutOfRangeException(nameof(spriteAnimation)); + } - if (TryGetAnimationTexture(textureName, spriteAnimationOveride, textureOverride, out var texture)) - { - AnimatedTextures[spriteAnimation] = texture; - } + if (TryGetAnimationTexture(textureName, spriteAnimationOveride, textureOverride, out var texture)) + { + AnimatedTextures[spriteAnimation] = texture; + } + } + + protected virtual bool TryGetAnimationTexture(string textureName, SpriteAnimations spriteAnimation, string textureOverride, out GameTexture texture) + { + var baseFilename = Path.GetFileNameWithoutExtension(textureName); + var extension = Path.GetExtension(textureName); + var animationTextureName = $"{baseFilename}_{spriteAnimation.ToString()?.ToLowerInvariant() ?? string.Empty}"; + + if (!string.IsNullOrWhiteSpace(textureOverride)) + { + animationTextureName = $"{animationTextureName}_{textureOverride}"; } - protected virtual bool TryGetAnimationTexture(string textureName, SpriteAnimations spriteAnimation, string textureOverride, out GameTexture texture) + texture = Globals.ContentManager.GetTexture(TextureType.Entity, $"{animationTextureName}{extension}"); + return texture != default; + } + + /// + /// Returns the direction to a player's selected target. + /// Original logic made by Daywalkr (Middle Ages: Online), thanks for sharing! + /// Modified by Arufonsu for the Intersect Engine along with support for 8 directions when enabled. + /// + /// entity's target + /// direction to player's selected target + public Direction DirectionToTarget(Entity en) + { + if (en == null) { - var baseFilename = Path.GetFileNameWithoutExtension(textureName); - var extension = Path.GetExtension(textureName); - var animationTextureName = $"{baseFilename}_{spriteAnimation.ToString()?.ToLowerInvariant() ?? string.Empty}"; + return Dir; + } - if (!string.IsNullOrWhiteSpace(textureOverride)) - { - animationTextureName = $"{animationTextureName}_{textureOverride}"; - } + var originMapController = MapInstance; + var targetMapController = en.MapInstance; - texture = Globals.ContentManager.GetTexture(TextureType.Entity, $"{animationTextureName}{extension}"); - return texture != default; + var originY = Y + originMapController.GridY * Options.MapHeight; + var originX = X + originMapController.GridX * Options.MapWidth; + var targetY = en.Y + targetMapController.GridY * Options.MapHeight; + var targetX = en.X + targetMapController.GridX * Options.MapWidth; + + // Calculate the offset between origin and target along both of their axis. + var yDiff = originY - targetY; + var xDiff = originX - targetX; + + // If Y offset is 0, direction is determined by X offset. + if (yDiff == 0) + { + return xDiff > 0 ? Direction.Left : Direction.Right; } - /// - /// Returns the direction to a player's selected target. - /// Original logic made by Daywalkr (Middle Ages: Online), thanks for sharing! - /// Modified by Arufonsu for the Intersect Engine along with support for 8 directions when enabled. - /// - /// entity's target - /// direction to player's selected target - public Direction DirectionToTarget(Entity en) + // If X offset is 0 or If diagonal movement is disabled, direction is determined by Y offset. + if (xDiff == 0 || !Options.Instance.MapOpts.EnableDiagonalMovement) { - if (en == null) - { - return Dir; - } + return yDiff > 0 ? Direction.Up : Direction.Down; + } - var originMapController = MapInstance; - var targetMapController = en.MapInstance; + // If both X and Y offset are non-zero, direction is determined by both offsets. + var xPositive = xDiff > 0; + var yPositive = yDiff > 0; + + if (xPositive) + { + return yPositive ? Direction.UpLeft : Direction.DownLeft; + } - var originY = Y + originMapController.GridY * Options.MapHeight; - var originX = X + originMapController.GridX * Options.MapWidth; - var targetY = en.Y + targetMapController.GridY * Options.MapHeight; - var targetX = en.X + targetMapController.GridX * Options.MapWidth; + return yPositive ? Direction.UpRight : Direction.DownRight; + } - // Calculate the offset between origin and target along both of their axis. - var yDiff = originY - targetY; - var xDiff = originX - targetX; + //Movement + /// + /// Returns -6 if the tile is blocked by a global (non-event) entity + /// Returns -5 if the tile is completely out of bounds. + /// Returns -4 if a tile is blocked because of a local event. + /// Returns -3 if a tile is blocked because of a Z dimension tile + /// Returns -2 if a tile does not exist or is blocked by a map attribute. + /// Returns -1 is a tile is passable. + /// Returns any value zero or greater matching the entity index that is in the way. + /// + /// + public int IsTileBlocked( + Point delta, + int z, + Guid mapId, + ref IEntity blockedBy, + bool ignoreAliveResources = true, + bool ignoreDeadResources = true, + bool ignoreNpcAvoids = true, + bool projectileTrigger = false + ) + { + var mapInstance = Maps.MapInstance.Get(mapId); + if (mapInstance == null) + { + return -2; + } - // If Y offset is 0, direction is determined by X offset. - if (yDiff == 0) + var gridX = mapInstance.GridX; + var gridY = mapInstance.GridY; + try + { + var tmpX = delta.X; + var tmpY = delta.Y; + var tmpMapId = Guid.Empty; + if (delta.X < 0) { - return xDiff > 0 ? Direction.Left : Direction.Right; + gridX--; + tmpX = Options.MapWidth - delta.X * -1; } - // If X offset is 0 or If diagonal movement is disabled, direction is determined by Y offset. - if (xDiff == 0 || !Options.Instance.MapOpts.EnableDiagonalMovement) + if (delta.Y < 0) { - return yDiff > 0 ? Direction.Up : Direction.Down; + gridY--; + tmpY = Options.MapHeight - delta.Y * -1; } - // If both X and Y offset are non-zero, direction is determined by both offsets. - var xPositive = xDiff > 0; - var yPositive = yDiff > 0; - - if (xPositive) + if (delta.X > Options.MapWidth - 1) { - return yPositive ? Direction.UpLeft : Direction.DownLeft; + gridX++; + tmpX = delta.X - Options.MapWidth; } - return yPositive ? Direction.UpRight : Direction.DownRight; - } - - //Movement - /// - /// Returns -6 if the tile is blocked by a global (non-event) entity - /// Returns -5 if the tile is completely out of bounds. - /// Returns -4 if a tile is blocked because of a local event. - /// Returns -3 if a tile is blocked because of a Z dimension tile - /// Returns -2 if a tile does not exist or is blocked by a map attribute. - /// Returns -1 is a tile is passable. - /// Returns any value zero or greater matching the entity index that is in the way. - /// - /// - public int IsTileBlocked( - Point delta, - int z, - Guid mapId, - ref IEntity blockedBy, - bool ignoreAliveResources = true, - bool ignoreDeadResources = true, - bool ignoreNpcAvoids = true, - bool projectileTrigger = false - ) - { - var mapInstance = Maps.MapInstance.Get(mapId); - if (mapInstance == null) + if (delta.Y > Options.MapHeight - 1) { - return -2; + gridY++; + tmpY = delta.Y - Options.MapHeight; } - var gridX = mapInstance.GridX; - var gridY = mapInstance.GridY; - try + if (gridX < 0 || gridY < 0 || gridX >= Globals.MapGridWidth || gridY >= Globals.MapGridHeight) { - var tmpX = delta.X; - var tmpY = delta.Y; - var tmpMapId = Guid.Empty; - if (delta.X < 0) - { - gridX--; - tmpX = Options.MapWidth - delta.X * -1; - } - - if (delta.Y < 0) - { - gridY--; - tmpY = Options.MapHeight - delta.Y * -1; - } + return -2; + } - if (delta.X > Options.MapWidth - 1) - { - gridX++; - tmpX = delta.X - Options.MapWidth; - } + tmpMapId = Globals.MapGrid[gridX, gridY]; - if (delta.Y > Options.MapHeight - 1) + foreach (var en in Globals.Entities) + { + if (en.Value == null) { - gridY++; - tmpY = delta.Y - Options.MapHeight; + continue; } - if (gridX < 0 || gridY < 0 || gridX >= Globals.MapGridWidth || gridY >= Globals.MapGridHeight) + if (en.Value == Globals.Me) { - return -2; + continue; } - - tmpMapId = Globals.MapGrid[gridX, gridY]; - - foreach (var en in Globals.Entities) + else { - if (en.Value == null) - { - continue; - } - - if (en.Value == Globals.Me) - { - continue; - } - else + if (en.Value.MapId == tmpMapId && + en.Value.X == tmpX && + en.Value.Y == tmpY && + en.Value.Z == Z) { - if (en.Value.MapId == tmpMapId && - en.Value.X == tmpX && - en.Value.Y == tmpY && - en.Value.Z == Z) + if (!(en.Value is Projectile)) { - if (!(en.Value is Projectile)) + switch (en.Value) { - switch (en.Value) - { - case Resource resource: - var resourceBase = resource.BaseResource; - if (resourceBase != null) + case Resource resource: + var resourceBase = resource.BaseResource; + if (resourceBase != null) + { + if (projectileTrigger) { - if (projectileTrigger) + bool isDead = resource.IsDead; + if (!ignoreAliveResources && !isDead || !ignoreDeadResources && isDead) { - bool isDead = resource.IsDead; - if (!ignoreAliveResources && !isDead || !ignoreDeadResources && isDead) - { - blockedBy = en.Value; - - return -6; - } + blockedBy = en.Value; - return -1; + return -6; } - if (resourceBase.WalkableAfter && resource.IsDead || - resourceBase.WalkableBefore && !resource.IsDead) - { - continue; - } + return -1; } - break; - case Player player: - //Return the entity key as this should block the player. Only exception is if the MapZone this entity is on is passable. - var entityMap = Maps.MapInstance.Get(player.MapId); - if (Options.Instance.Passability.Passable[(int)entityMap.ZoneType]) + if (resourceBase.WalkableAfter && resource.IsDead || + resourceBase.WalkableBefore && !resource.IsDead) { continue; } - break; - } + } + break; + + case Player player: + //Return the entity key as this should block the player. Only exception is if the MapZone this entity is on is passable. + var entityMap = Maps.MapInstance.Get(player.MapId); + if (Options.Instance.Passability.Passable[(int)entityMap.ZoneType]) + { + continue; + } + break; + } - blockedBy = en.Value; + blockedBy = en.Value; - return -6; - } + return -6; } } } + } - if (Maps.MapInstance.Get(tmpMapId) != null) + if (Maps.MapInstance.Get(tmpMapId) != null) + { + foreach (var en in Maps.MapInstance.Get(tmpMapId).LocalEntities) { - foreach (var en in Maps.MapInstance.Get(tmpMapId).LocalEntities) + if (en.Value == null) { - if (en.Value == null) - { - continue; - } + continue; + } - if (en.Value.MapId == tmpMapId && - en.Value.X == tmpX && - en.Value.Y == tmpY && - en.Value.Z == Z && - !en.Value.Passable) - { - blockedBy = en.Value; + if (en.Value.MapId == tmpMapId && + en.Value.X == tmpX && + en.Value.Y == tmpY && + en.Value.Z == Z && + !en.Value.Passable) + { + blockedBy = en.Value; - return -4; - } + return -4; } + } - foreach (var en in Maps.MapInstance.Get(tmpMapId).LocalCritters) + foreach (var en in Maps.MapInstance.Get(tmpMapId).LocalCritters) + { + if (en.Value == null) { - if (en.Value == null) - { - continue; - } + continue; + } - if (en.Value.MapId == tmpMapId && - en.Value.X == tmpX && - en.Value.Y == tmpY && - en.Value.Z == Z && - !en.Value.Passable) - { - blockedBy = en.Value as Critter; + if (en.Value.MapId == tmpMapId && + en.Value.X == tmpX && + en.Value.Y == tmpY && + en.Value.Z == Z && + !en.Value.Passable) + { + blockedBy = en.Value as Critter; - return -4; - } + return -4; } } + } - var gameMap = Maps.MapInstance.Get(Globals.MapGrid[gridX, gridY]); - if (gameMap != null) + var gameMap = Maps.MapInstance.Get(Globals.MapGrid[gridX, gridY]); + if (gameMap != null) + { + if (gameMap.Attributes[tmpX, tmpY] != null) { - if (gameMap.Attributes[tmpX, tmpY] != null) + if (gameMap.Attributes[tmpX, tmpY].Type == MapAttribute.Blocked || (gameMap.Attributes[tmpX, tmpY].Type == MapAttribute.Animation && ((MapAnimationAttribute)gameMap.Attributes[tmpX, tmpY]).IsBlock)) { - if (gameMap.Attributes[tmpX, tmpY].Type == MapAttribute.Blocked || (gameMap.Attributes[tmpX, tmpY].Type == MapAttribute.Animation && ((MapAnimationAttribute)gameMap.Attributes[tmpX, tmpY]).IsBlock)) - { - return -2; - } - else if (gameMap.Attributes[tmpX, tmpY].Type == MapAttribute.ZDimension) + return -2; + } + else if (gameMap.Attributes[tmpX, tmpY].Type == MapAttribute.ZDimension) + { + if (((MapZDimensionAttribute)gameMap.Attributes[tmpX, tmpY]).BlockedLevel - 1 == z) { - if (((MapZDimensionAttribute)gameMap.Attributes[tmpX, tmpY]).BlockedLevel - 1 == z) - { - return -3; - } + return -3; } - else if (gameMap.Attributes[tmpX, tmpY].Type == MapAttribute.NpcAvoid) + } + else if (gameMap.Attributes[tmpX, tmpY].Type == MapAttribute.NpcAvoid) + { + if (!ignoreNpcAvoids) { - if (!ignoreNpcAvoids) - { - return -2; - } + return -2; } } } - else - { - return -5; - } - - return -1; } - catch + else { - return -2; + return -5; } - } - ~Entity() + return -1; + } + catch { - Dispose(); + return -2; } + } + ~Entity() + { + Dispose(); + } - } } diff --git a/Intersect.Client/Entities/Events/Dialog.cs b/Intersect.Client/Entities/Events/Dialog.cs index cd9075be6e..93f47a7a70 100644 --- a/Intersect.Client/Entities/Events/Dialog.cs +++ b/Intersect.Client/Entities/Events/Dialog.cs @@ -1,27 +1,25 @@ -namespace Intersect.Client.Entities.Events -{ +namespace Intersect.Client.Entities.Events; - public partial class Dialog - { - public Guid EventId; +public partial class Dialog +{ - public string Face = ""; + public Guid EventId; - public string Opt1 = ""; + public string Face = ""; - public string Opt2 = ""; + public string Opt1 = ""; - public string Opt3 = ""; + public string Opt2 = ""; - public string Opt4 = ""; + public string Opt3 = ""; - public string Prompt = ""; + public string Opt4 = ""; - public int ResponseSent; + public string Prompt = ""; - public int Type; + public int ResponseSent; - } + public int Type; } diff --git a/Intersect.Client/Entities/Events/Event.cs b/Intersect.Client/Entities/Events/Event.cs index 2ebeb48be4..4f16e14140 100644 --- a/Intersect.Client/Entities/Events/Event.cs +++ b/Intersect.Client/Entities/Events/Event.cs @@ -9,306 +9,305 @@ using Intersect.Logging; using Intersect.Network.Packets.Server; -namespace Intersect.Client.Entities.Events +namespace Intersect.Client.Entities.Events; + +public partial class Event : Entity { - public partial class Event : Entity - { - private bool _drawCompletedWithoutTexture = false; + private bool _drawCompletedWithoutTexture = false; - public string Desc { get; set; } = string.Empty; + public string Desc { get; set; } = string.Empty; - public bool DirectionFix { get; set; } + public bool DirectionFix { get; set; } - public bool DisablePreview { get; set; } + public bool DisablePreview { get; set; } - public string FaceGraphic { get; set; } = string.Empty; + public string FaceGraphic { get; set; } = string.Empty; - public EventGraphic Graphic { get; set; } = new EventGraphic(); + public EventGraphic Graphic { get; set; } = new EventGraphic(); - public int Layer { get; set; } + public int Layer { get; set; } - private int mOldRenderLevel { get; set; } + private int mOldRenderLevel { get; set; } - private MapInstance mOldRenderMap { get; set; } + private MapInstance mOldRenderMap { get; set; } - private int mOldRenderY { get; set; } + private int mOldRenderY { get; set; } - public int RenderLevel { get; set; } = 1; + public int RenderLevel { get; set; } = 1; - public bool WalkingAnim { get; set; } = true; + public bool WalkingAnim { get; set; } = true; - public EventTrigger Trigger { get; set; } + public EventTrigger Trigger { get; set; } - protected override Pointf CenterOffset + protected override Pointf CenterOffset + { + get { - get + switch (Graphic.Type) { - switch (Graphic.Type) - { - case EventGraphicType.None: - return Animations.Count == 0 ? Pointf.Empty : Pointf.UnitY * Options.TileHeight / 2f; + case EventGraphicType.None: + return Animations.Count == 0 ? Pointf.Empty : Pointf.UnitY * Options.TileHeight / 2f; - case EventGraphicType.Sprite: - return base.CenterOffset; + case EventGraphicType.Sprite: + return base.CenterOffset; - case EventGraphicType.Tileset: - return Pointf.UnitY * Options.TileHeight * (Graphic.Height + 1) / 2f; + case EventGraphicType.Tileset: + return Pointf.UnitY * Options.TileHeight * (Graphic.Height + 1) / 2f; - default: - Log.Error($"Unimplemented graphic type: {Graphic.Type}"); - return Pointf.Empty; - } + default: + Log.Error($"Unimplemented graphic type: {Graphic.Type}"); + return Pointf.Empty; } } + } - public Event(Guid id, EventEntityPacket packet) : base(id, packet, EntityType.Event) - { - mRenderPriority = 1; - } + public Event(Guid id, EventEntityPacket packet) : base(id, packet, EntityType.Event) + { + mRenderPriority = 1; + } - public override void Load(EntityPacket packet) + public override void Load(EntityPacket packet) + { + if (!(packet is EventEntityPacket eventEntityPacket)) { - if (!(packet is EventEntityPacket eventEntityPacket)) - { - Log.Error($"Received invalid packet for {nameof(Event)}: {packet?.GetType()?.FullName}"); - return; - } - DirectionFix = eventEntityPacket.DirectionFix; - WalkingAnim = eventEntityPacket.WalkingAnim; - DisablePreview = eventEntityPacket.DisablePreview; - Desc = eventEntityPacket.Description; - Graphic = eventEntityPacket.Graphic; - RenderLevel = eventEntityPacket.RenderLayer; - Trigger = eventEntityPacket.Trigger; + Log.Error($"Received invalid packet for {nameof(Event)}: {packet?.GetType()?.FullName}"); + return; + } + DirectionFix = eventEntityPacket.DirectionFix; + WalkingAnim = eventEntityPacket.WalkingAnim; + DisablePreview = eventEntityPacket.DisablePreview; + Desc = eventEntityPacket.Description; + Graphic = eventEntityPacket.Graphic; + RenderLevel = eventEntityPacket.RenderLayer; + Trigger = eventEntityPacket.Trigger; - _drawCompletedWithoutTexture = Graphic.Type != EventGraphicType.Tileset; + _drawCompletedWithoutTexture = Graphic.Type != EventGraphicType.Tileset; - base.Load(packet); + base.Load(packet); - if (!string.IsNullOrEmpty(Graphic?.Filename)) - { - Sprite = Graphic.Filename; - } + if (!string.IsNullOrEmpty(Graphic?.Filename)) + { + Sprite = Graphic.Filename; } + } - public override bool Update() + public override bool Update() + { + var success = base.Update(); + if (!WalkingAnim) { - var success = base.Update(); - if (!WalkingAnim) - { - WalkFrame = 0; - } - - return success; + WalkFrame = 0; } - protected bool TryEnsureTexture(out GameTexture texture) - { - if (_drawCompletedWithoutTexture) - { - texture = Texture; - return texture != default; - } + return success; + } - LoadTextures(Sprite); + protected bool TryEnsureTexture(out GameTexture texture) + { + if (_drawCompletedWithoutTexture) + { texture = Texture; - _drawCompletedWithoutTexture = (texture == default); - return !_drawCompletedWithoutTexture; + return texture != default; } - public override void Draw() + LoadTextures(Sprite); + texture = Texture; + _drawCompletedWithoutTexture = (texture == default); + return !_drawCompletedWithoutTexture; + } + + public override void Draw() + { + WorldPos.Reset(); + if (MapInstance == default || !Globals.GridMaps.Contains(MapId) || !TryEnsureTexture(out var texture)) { - WorldPos.Reset(); - if (MapInstance == default || !Globals.GridMaps.Contains(MapId) || !TryEnsureTexture(out var texture)) - { - return; - } + return; + } - FloatRect srcRectangle; - switch (Graphic.Type) - { - case EventGraphicType.Sprite: //Sprite - base.Draw(); - return; - - case EventGraphicType.Tileset: //Tile - var width = (Graphic.Width + 1) * Options.TileWidth; - var height = (Graphic.Height + 1) * Options.TileHeight; - srcRectangle = new FloatRect( - Graphic.X * Options.TileWidth, - Graphic.Y * Options.TileHeight, - width, - height - ); - break; + FloatRect srcRectangle; + switch (Graphic.Type) + { + case EventGraphicType.Sprite: //Sprite + base.Draw(); + return; - default: - return; - } + case EventGraphicType.Tileset: //Tile + var width = (Graphic.Width + 1) * Options.TileWidth; + var height = (Graphic.Height + 1) * Options.TileHeight; + srcRectangle = new FloatRect( + Graphic.X * Options.TileWidth, + Graphic.Y * Options.TileHeight, + width, + height + ); + break; + + default: + return; + } - var map = Maps.MapInstance.Get(MapId); + var map = Maps.MapInstance.Get(MapId); - var destRectangle = new FloatRect - { - X = map.GetX() + X * Options.TileWidth + OffsetX, - Y = map.GetY() + Y * Options.TileHeight + OffsetY, - Width = Math.Max(Options.TileWidth, srcRectangle.Width), - Height = Math.Max(Options.TileHeight, srcRectangle.Height), - }; + var destRectangle = new FloatRect + { + X = map.GetX() + X * Options.TileWidth + OffsetX, + Y = map.GetY() + Y * Options.TileHeight + OffsetY, + Width = Math.Max(Options.TileWidth, srcRectangle.Width), + Height = Math.Max(Options.TileHeight, srcRectangle.Height), + }; - if (srcRectangle.Width > Options.TileWidth) - { - destRectangle.X -= (srcRectangle.Width - Options.TileWidth) / 2; - } + if (srcRectangle.Width > Options.TileWidth) + { + destRectangle.X -= (srcRectangle.Width - Options.TileWidth) / 2; + } - if (srcRectangle.Height > Options.TileHeight) - { - destRectangle.Y -= srcRectangle.Height - Options.TileHeight; - } + if (srcRectangle.Height > Options.TileHeight) + { + destRectangle.Y -= srcRectangle.Height - Options.TileHeight; + } - destRectangle.X = (int)Math.Ceiling(destRectangle.X); - destRectangle.Y = (int)Math.Ceiling(destRectangle.Y); + destRectangle.X = (int)Math.Ceiling(destRectangle.X); + destRectangle.Y = (int)Math.Ceiling(destRectangle.Y); - // Set up our targetting rectangle. - // If we're smaller than a tile, force the target size to a tile. - WorldPos = destRectangle; + // Set up our targetting rectangle. + // If we're smaller than a tile, force the target size to a tile. + WorldPos = destRectangle; - Graphics.DrawGameTexture(texture, srcRectangle, destRectangle, Color.White); - } + Graphics.DrawGameTexture(texture, srcRectangle, destRectangle, Color.White); + } - public override void LoadTextures(string textureName) + public override void LoadTextures(string textureName) + { + switch (Graphic.Type) { - switch (Graphic.Type) - { - case EventGraphicType.Tileset: - Texture = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Tileset, textureName); - break; + case EventGraphicType.Tileset: + Texture = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Tileset, textureName); + break; - case EventGraphicType.Sprite: - base.LoadTextures(textureName); - break; + case EventGraphicType.Sprite: + base.LoadTextures(textureName); + break; - default: - break; - } + default: + break; } + } - public override HashSet DetermineRenderOrder(HashSet renderList, IMapInstance map) + public override HashSet DetermineRenderOrder(HashSet renderList, IMapInstance map) + { + if (RenderLevel == 1) { - if (RenderLevel == 1) - { - return base.DetermineRenderOrder(renderList, map); - } + return base.DetermineRenderOrder(renderList, map); + } - renderList?.Remove(this); - if (map == null || Globals.Me == null || Globals.Me.MapInstance == null) - { - return null; - } + renderList?.Remove(this); + if (map == null || Globals.Me == null || Globals.Me.MapInstance == null) + { + return null; + } - var gridX = Globals.Me.MapInstance.GridX; - var gridY = Globals.Me.MapInstance.GridY; - for (var x = gridX - 1; x <= gridX + 1; x++) + var gridX = Globals.Me.MapInstance.GridX; + var gridY = Globals.Me.MapInstance.GridY; + for (var x = gridX - 1; x <= gridX + 1; x++) + { + for (var y = gridY - 1; y <= gridY + 1; y++) { - for (var y = gridY - 1; y <= gridY + 1; y++) + if (x >= 0 && + x < Globals.MapGridWidth && + y >= 0 && + y < Globals.MapGridHeight && + Globals.MapGrid[x, y] != Guid.Empty) { - if (x >= 0 && - x < Globals.MapGridWidth && - y >= 0 && - y < Globals.MapGridHeight && - Globals.MapGrid[x, y] != Guid.Empty) + if (Globals.MapGrid[x, y] != MapId) { - if (Globals.MapGrid[x, y] != MapId) - { - continue; - } - - if (RenderLevel == 0) - { - y--; - } - else if (RenderLevel == 2) - { - y++; - } - - var priority = mRenderPriority; - if (Z != 0) - { - priority += 3; - } - - var maps = y - (gridY - 2); - var renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * maps + Y]; - - // If bugs arise from switching to the above, remove and uncomment this - //HashSet renderSet = null; - //if (y == gridY - 2) - //{ - // renderSet = Graphics.RenderingEntities[priority, Y]; - //} - //else if (y == gridY - 1) - //{ - // renderSet = Graphics.RenderingEntities[priority, Options.MapHeight + Y]; - //} - //else if (y == gridY) - //{ - // renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * 2 + Y]; - //} - //else if (y == gridY + 1) - //{ - // renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * 3 + Y]; - //} - //else if (y == gridY + 2) - //{ - // renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * 4 + Y]; - //} - - renderSet?.Add(this); - renderList = renderSet; - - return renderList; + continue; } + + if (RenderLevel == 0) + { + y--; + } + else if (RenderLevel == 2) + { + y++; + } + + var priority = mRenderPriority; + if (Z != 0) + { + priority += 3; + } + + var maps = y - (gridY - 2); + var renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * maps + Y]; + + // If bugs arise from switching to the above, remove and uncomment this + //HashSet renderSet = null; + //if (y == gridY - 2) + //{ + // renderSet = Graphics.RenderingEntities[priority, Y]; + //} + //else if (y == gridY - 1) + //{ + // renderSet = Graphics.RenderingEntities[priority, Options.MapHeight + Y]; + //} + //else if (y == gridY) + //{ + // renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * 2 + Y]; + //} + //else if (y == gridY + 1) + //{ + // renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * 3 + Y]; + //} + //else if (y == gridY + 2) + //{ + // renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * 4 + Y]; + //} + + renderSet?.Add(this); + renderList = renderSet; + + return renderList; } } - - return renderList; } - public override float GetTop(int overrideHeight = -1) - { - float heightScale; - switch (Graphic.Type) - { - case EventGraphicType.Sprite: - return base.GetTop(overrideHeight); + return renderList; + } - case EventGraphicType.Tileset: - heightScale = Graphic.Height + 1; - break; + public override float GetTop(int overrideHeight = -1) + { + float heightScale; + switch (Graphic.Type) + { + case EventGraphicType.Sprite: + return base.GetTop(overrideHeight); - case EventGraphicType.None: - heightScale = Animations.Count > 0 ? 1 : 0.5f; - break; + case EventGraphicType.Tileset: + heightScale = Graphic.Height + 1; + break; - default: - throw new IndexOutOfRangeException($"Unsupported {nameof(EventGraphicType)} '{Graphic.Type}'"); - } + case EventGraphicType.None: + heightScale = Animations.Count > 0 ? 1 : 0.5f; + break; - var top = base.GetTop(0); - var offset = heightScale * Options.TileHeight; - return top - offset; + default: + throw new IndexOutOfRangeException($"Unsupported {nameof(EventGraphicType)} '{Graphic.Type}'"); } - public override void DrawName(Color textColor, Color borderColor, Color backgroundColor) - { - base.DrawName( - textColor: textColor ?? new Color(CustomColors.Names.Events.Name), - borderColor: borderColor ?? new Color(CustomColors.Names.Events.Outline), - backgroundColor: backgroundColor ?? new Color(CustomColors.Names.Events.Background) - ); - } + var top = base.GetTop(0); + var offset = heightScale * Options.TileHeight; + return top - offset; + } - ~Event() => Dispose(); + public override void DrawName(Color textColor, Color borderColor, Color backgroundColor) + { + base.DrawName( + textColor: textColor ?? new Color(CustomColors.Names.Events.Name), + borderColor: borderColor ?? new Color(CustomColors.Names.Events.Outline), + backgroundColor: backgroundColor ?? new Color(CustomColors.Names.Events.Background) + ); } + + ~Event() => Dispose(); } diff --git a/Intersect.Client/Entities/Events/Hold.cs b/Intersect.Client/Entities/Events/Hold.cs index 7568ff48ce..d07508f8d1 100644 --- a/Intersect.Client/Entities/Events/Hold.cs +++ b/Intersect.Client/Entities/Events/Hold.cs @@ -1,19 +1,17 @@ -namespace Intersect.Client.Entities.Events -{ +namespace Intersect.Client.Entities.Events; - public partial class Hold - { - public Guid EventId; +public partial class Hold +{ - public Guid MapId; + public Guid EventId; - public Hold(Guid eventId, Guid mapId) - { - EventId = eventId; - MapId = mapId; - } + public Guid MapId; + public Hold(Guid eventId, Guid mapId) + { + EventId = eventId; + MapId = mapId; } } diff --git a/Intersect.Client/Entities/FriendInstance.cs b/Intersect.Client/Entities/FriendInstance.cs index 4f8ec576d6..e27f810d1e 100644 --- a/Intersect.Client/Entities/FriendInstance.cs +++ b/Intersect.Client/Entities/FriendInstance.cs @@ -1,15 +1,14 @@ using Intersect.Client.Framework.Entities; -namespace Intersect.Client.Entities +namespace Intersect.Client.Entities; + +public partial class FriendInstance : IFriendInstance { - public partial class FriendInstance : IFriendInstance - { - public string Map { get; set; } + public string Map { get; set; } - public string Name { get; set; } + public string Name { get; set; } - public bool Online { get; set; } = false; + public bool Online { get; set; } = false; - } } diff --git a/Intersect.Client/Entities/HotbarInstance.cs b/Intersect.Client/Entities/HotbarInstance.cs index dd03980209..7d39792ca4 100644 --- a/Intersect.Client/Entities/HotbarInstance.cs +++ b/Intersect.Client/Entities/HotbarInstance.cs @@ -2,21 +2,20 @@ using Intersect.Enums; using Newtonsoft.Json; -namespace Intersect.Client.Entities -{ - public partial class HotbarInstance : IHotbarInstance - { +namespace Intersect.Client.Entities; - public Guid BagId { get; set; } = Guid.Empty; +public partial class HotbarInstance : IHotbarInstance +{ - public Guid ItemOrSpellId { get; set; } = Guid.Empty; + public Guid BagId { get; set; } = Guid.Empty; - public int[] PreferredStatBuffs { get; set; } = new int[Enum.GetValues().Length]; + public Guid ItemOrSpellId { get; set; } = Guid.Empty; - public void Load(string data) - { - JsonConvert.PopulateObject(data, this); - } + public int[] PreferredStatBuffs { get; set; } = new int[Enum.GetValues().Length]; + public void Load(string data) + { + JsonConvert.PopulateObject(data, this); } + } diff --git a/Intersect.Client/Entities/PartyMember.cs b/Intersect.Client/Entities/PartyMember.cs index 8744e08950..b353343453 100644 --- a/Intersect.Client/Entities/PartyMember.cs +++ b/Intersect.Client/Entities/PartyMember.cs @@ -1,31 +1,29 @@ using Intersect.Client.Framework.Entities; using Intersect.Enums; -namespace Intersect.Client.Entities -{ +namespace Intersect.Client.Entities; - public partial class PartyMember : IPartyMember - { - public Guid Id { get; set; } +public partial class PartyMember : IPartyMember +{ - public int Level { get; set; } + public Guid Id { get; set; } - public long[] MaxVital { get; set; } = new long[Enum.GetValues().Length]; + public int Level { get; set; } - public string Name { get; set; } + public long[] MaxVital { get; set; } = new long[Enum.GetValues().Length]; - public long[] Vital { get; set; } = new long[Enum.GetValues().Length]; + public string Name { get; set; } - public PartyMember(Guid id, string name, long[] vital, long[] maxVital, int level) - { - Id = id; - Name = name; - Vital = vital; - MaxVital = maxVital; - Level = level; - } + public long[] Vital { get; set; } = new long[Enum.GetValues().Length]; + public PartyMember(Guid id, string name, long[] vital, long[] maxVital, int level) + { + Id = id; + Name = name; + Vital = vital; + MaxVital = maxVital; + Level = level; } } diff --git a/Intersect.Client/Entities/Player.cs b/Intersect.Client/Entities/Player.cs index c5b6458f19..e7c6e03dde 100644 --- a/Intersect.Client/Entities/Player.cs +++ b/Intersect.Client/Entities/Player.cs @@ -23,1923 +23,1940 @@ using Intersect.Utilities; using MapAttribute = Intersect.Enums.MapAttribute; -namespace Intersect.Client.Entities -{ +namespace Intersect.Client.Entities; - public partial class Player : Entity, IPlayer - { - public delegate void InventoryUpdated(); +public partial class Player : Entity, IPlayer +{ + + public delegate void InventoryUpdated(); - private Guid _class; + private Guid _class; - public Guid Class + public Guid Class + { + get => _class; + set { - get => _class; - set + if (_class == value) { - if (_class == value) - { - return; - } - - _class = value; - LoadAnimationTexture(string.IsNullOrWhiteSpace(TransformedSprite) ? Sprite : TransformedSprite, SpriteAnimations.Attack); + return; } + + _class = value; + LoadAnimationTexture(string.IsNullOrWhiteSpace(TransformedSprite) ? Sprite : TransformedSprite, SpriteAnimations.Attack); } + } - public Access AccessLevel { get; set; } + public Access AccessLevel { get; set; } - public long Experience { get; set; } = 0; + public long Experience { get; set; } = 0; - public long ExperienceToNextLevel { get; set; } = 0; + public long ExperienceToNextLevel { get; set; } = 0; - IReadOnlyList IPlayer.Friends => Friends; + IReadOnlyList IPlayer.Friends => Friends; - public List Friends { get; set; } = new(); + public List Friends { get; set; } = new(); - IReadOnlyList IPlayer.HotbarSlots => Hotbar.ToList(); + IReadOnlyList IPlayer.HotbarSlots => Hotbar.ToList(); - public HotbarInstance[] Hotbar { get; set; } = new HotbarInstance[Options.Instance.PlayerOpts.HotbarSlotCount]; + public HotbarInstance[] Hotbar { get; set; } = new HotbarInstance[Options.Instance.PlayerOpts.HotbarSlotCount]; - public InventoryUpdated InventoryUpdatedDelegate { get; set; } + public InventoryUpdated InventoryUpdatedDelegate { get; set; } - IReadOnlyDictionary IPlayer.ItemCooldowns => ItemCooldowns; + IReadOnlyDictionary IPlayer.ItemCooldowns => ItemCooldowns; - public Dictionary ItemCooldowns { get; set; } = new(); + public Dictionary ItemCooldowns { get; set; } = new(); - private Entity mLastBumpedEvent; + private Entity mLastBumpedEvent; - private List mParty; + private List mParty; - private Direction _lastMoveDirection; + private Direction _lastMoveDirection; - public override Direction MoveDir + public override Direction MoveDir + { + get => base.MoveDir; + set { - get => base.MoveDir; - set - { - _lastMoveDirection = base.MoveDir; - base.MoveDir = value; - } + _lastMoveDirection = base.MoveDir; + base.MoveDir = value; } + } - IReadOnlyDictionary IPlayer.QuestProgress => QuestProgress; + IReadOnlyDictionary IPlayer.QuestProgress => QuestProgress; - public Dictionary QuestProgress { get; set; } = new(); + public Dictionary QuestProgress { get; set; } = new(); - public Guid[] HiddenQuests { get; set; } = new Guid[0]; + public Guid[] HiddenQuests { get; set; } = new Guid[0]; - IReadOnlyDictionary IPlayer.SpellCooldowns => SpellCooldowns; + IReadOnlyDictionary IPlayer.SpellCooldowns => SpellCooldowns; - public Dictionary SpellCooldowns { get; set; } = new(); + public Dictionary SpellCooldowns { get; set; } = new(); - public int StatPoints { get; set; } = 0; + public int StatPoints { get; set; } = 0; - public EntityBox TargetBox { get; set; } + public EntityBox TargetBox { get; set; } - public PlayerStatusWindow StatusWindow { get; set; } + public PlayerStatusWindow StatusWindow { get; set; } - public Guid TargetIndex { get; set; } + public Guid TargetIndex { get; set; } - TargetType IPlayer.TargetType => (TargetType)TargetType; + TargetType IPlayer.TargetType => (TargetType)TargetType; - public int TargetType { get; set; } + public int TargetType { get; set; } - public long CombatTimer { get; set; } + public long CombatTimer { get; set; } - public long IsCastingCheckTimer { get; set; } + public long IsCastingCheckTimer { get; set; } - public long GlobalCooldown { get; set; } + public long GlobalCooldown { get; set; } - // Target data - private long mlastTargetScanTime; + // Target data + private long mlastTargetScanTime; - Guid mlastTargetScanMap = Guid.Empty; + Guid mlastTargetScanMap = Guid.Empty; - Point mlastTargetScanLocation = new(-1, -1); + Point mlastTargetScanLocation = new(-1, -1); - Dictionary mlastTargetList = new(); // Entity, Last Time Selected + Dictionary mlastTargetList = new(); // Entity, Last Time Selected - Entity mLastEntitySelected; + Entity mLastEntitySelected; - private Dictionary mLastHotbarUseTime = new(); - private int mHotbarUseDelay = 150; + private Dictionary mLastHotbarUseTime = new(); + private int mHotbarUseDelay = 150; - /// - /// Name of our guild if we are in one. - /// - public string Guild { get; set; } + /// + /// Name of our guild if we are in one. + /// + public string Guild { get; set; } - string IPlayer.GuildName => Guild; + string IPlayer.GuildName => Guild; - /// - /// Index of our rank where 0 is the leader - /// - public int Rank { get; set; } + /// + /// Index of our rank where 0 is the leader + /// + public int Rank { get; set; } - /// - /// Returns whether or not we are in a guild by checking to see if we are assigned a guild name - /// - public bool IsInGuild => !string.IsNullOrWhiteSpace(Guild); + /// + /// Returns whether or not we are in a guild by checking to see if we are assigned a guild name + /// + public bool IsInGuild => !string.IsNullOrWhiteSpace(Guild); - /// - /// Obtains our rank and permissions from the game config - /// - public GuildRank GuildRank => IsInGuild ? Options.Instance.Guild.Ranks[Math.Max(0, Math.Min(Rank, Options.Instance.Guild.Ranks.Length - 1))] : null; + /// + /// Obtains our rank and permissions from the game config + /// + public GuildRank GuildRank => IsInGuild ? Options.Instance.Guild.Ranks[Math.Max(0, Math.Min(Rank, Options.Instance.Guild.Ranks.Length - 1))] : null; - /// - /// Contains a record of all members of this player's guild. - /// - public GuildMember[] GuildMembers = new GuildMember[0]; + /// + /// Contains a record of all members of this player's guild. + /// + public GuildMember[] GuildMembers = new GuildMember[0]; - public Player(Guid id, PlayerEntityPacket packet) : base(id, packet, EntityType.Player) + public Player(Guid id, PlayerEntityPacket packet) : base(id, packet, EntityType.Player) + { + for (var i = 0; i < Options.Instance.PlayerOpts.HotbarSlotCount; i++) { - for (var i = 0; i < Options.Instance.PlayerOpts.HotbarSlotCount; i++) - { - Hotbar[i] = new HotbarInstance(); - } - - mRenderPriority = 2; + Hotbar[i] = new HotbarInstance(); } - IReadOnlyList IPlayer.PartyMembers => Party; + mRenderPriority = 2; + } + + IReadOnlyList IPlayer.PartyMembers => Party; - public List Party + public List Party + { + get { - get + if (mParty == null) { - if (mParty == null) - { - mParty = new List(); - } - - return mParty; + mParty = new List(); } + + return mParty; } + } - public override Guid MapId + public override Guid MapId + { + get => base.MapId; + set { - get => base.MapId; - set + if (value != base.MapId) { - if (value != base.MapId) + var oldMap = Maps.MapInstance.Get(base.MapId); + var newMap = Maps.MapInstance.Get(value); + base.MapId = value; + if (Globals.Me == this) { - var oldMap = Maps.MapInstance.Get(base.MapId); - var newMap = Maps.MapInstance.Get(value); - base.MapId = value; - if (Globals.Me == this) + if (Maps.MapInstance.Get(Globals.Me.MapId) != null) { - if (Maps.MapInstance.Get(Globals.Me.MapId) != null) - { - Audio.PlayMusic(Maps.MapInstance.Get(Globals.Me.MapId).Music, ClientConfiguration.Instance.MusicFadeTimer, ClientConfiguration.Instance.MusicFadeTimer, true); - } + Audio.PlayMusic(Maps.MapInstance.Get(Globals.Me.MapId).Music, ClientConfiguration.Instance.MusicFadeTimer, ClientConfiguration.Instance.MusicFadeTimer, true); + } - if (newMap != null && oldMap != null) - { - newMap.CompareEffects(oldMap); - } + if (newMap != null && oldMap != null) + { + newMap.CompareEffects(oldMap); } } } } + } - public bool IsFriend(IPlayer player) - { - return Friends.Any( - friend => player != null && - string.Equals(player.Name, friend.Name, StringComparison.CurrentCultureIgnoreCase)); - } + public bool IsFriend(IPlayer player) + { + return Friends.Any( + friend => player != null && + string.Equals(player.Name, friend.Name, StringComparison.CurrentCultureIgnoreCase)); + } - public bool IsGuildMate(IPlayer player) - { - return GuildMembers.Any( - guildMate => - player != null && - string.Equals(player.Name, guildMate.Name, StringComparison.CurrentCultureIgnoreCase)); - } + public bool IsGuildMate(IPlayer player) + { + return GuildMembers.Any( + guildMate => + player != null && + string.Equals(player.Name, guildMate.Name, StringComparison.CurrentCultureIgnoreCase)); + } - bool IPlayer.IsInParty => IsInParty(); + bool IPlayer.IsInParty => IsInParty(); - public bool IsInParty() - { - return Party.Count > 0; - } + public bool IsInParty() + { + return Party.Count > 0; + } + + public bool IsInMyParty(IPlayer player) => player != null && IsInMyParty(player.Id); - public bool IsInMyParty(IPlayer player) => player != null && IsInMyParty(player.Id); + public bool IsInMyParty(Guid id) => Party.Any(member => member.Id == id); - public bool IsInMyParty(Guid id) => Party.Any(member => member.Id == id); + public bool IsInMyGuild(IPlayer player) => IsInGuild && player != null && player.GuildName == Guild; - public bool IsInMyGuild(IPlayer player) => IsInGuild && player != null && player.GuildName == Guild; + public bool IsBusy => !(Globals.EventHolds.Count == 0 && + !Globals.MoveRouteActive && + Globals.GameShop == null && + Globals.InBank == false && + Globals.InCraft == false && + Globals.InTrade == false && + !Interface.Interface.HasInputFocus()); - public bool IsBusy => !(Globals.EventHolds.Count == 0 && - !Globals.MoveRouteActive && - Globals.GameShop == null && - Globals.InBank == false && - Globals.InCraft == false && - Globals.InTrade == false && - !Interface.Interface.HasInputFocus()); + public override bool Update() + { - public override bool Update() + if (Globals.Me == this) { + HandleInput(); + } - if (Globals.Me == this) + + if (!IsBusy) + { + if (this == Globals.Me && IsMoving == false) { - HandleInput(); + ProcessDirectionalInput(); } - - if (!IsBusy) + if (Controls.KeyDown(Control.AttackInteract)) { - if (this == Globals.Me && IsMoving == false) - { - ProcessDirectionalInput(); - } - - if (Controls.KeyDown(Control.AttackInteract)) + if (IsCasting) { - if (IsCasting) + if (IsCastingCheckTimer < Timing.Global.Milliseconds && + Options.Combat.EnableCombatChatMessages) { - if (IsCastingCheckTimer < Timing.Global.Milliseconds && - Options.Combat.EnableCombatChatMessages) - { - ChatboxMsg.AddMessage(new ChatboxMsg(Strings.Combat.AttackWhileCastingDeny, - CustomColors.Alerts.Declined, ChatMessageType.Combat)); - IsCastingCheckTimer = Timing.Global.Milliseconds + 350; - } - } - else if (!Globals.Me.TryAttack()) - { - if (!Globals.Me.IsAttacking && (!IsMoving || Options.Instance.PlayerOpts.AllowCombatMovement)) - { - Globals.Me.AttackTimer = Timing.Global.Milliseconds + Globals.Me.CalculateAttackTime(); - } + ChatboxMsg.AddMessage(new ChatboxMsg(Strings.Combat.AttackWhileCastingDeny, + CustomColors.Alerts.Declined, ChatMessageType.Combat)); + IsCastingCheckTimer = Timing.Global.Milliseconds + 350; } } - - //Holding block button for "auto blocking" - if (Controls.KeyDown(Control.Block)) + else if (!Globals.Me.TryAttack()) { - TryBlock(); + if (!Globals.Me.IsAttacking && (!IsMoving || Options.Instance.PlayerOpts.AllowCombatMovement)) + { + Globals.Me.AttackTimer = Timing.Global.Milliseconds + Globals.Me.CalculateAttackTime(); + } } } - if (TargetBox == default && this == Globals.Me && Interface.Interface.GameUi != default) - { - // If for WHATEVER reason the box hasn't been created, create it. - TargetBox = new EntityBox(Interface.Interface.GameUi.GameCanvas, EntityType.Player, null); - TargetBox.Hide(); - } - else if (TargetIndex != default) + //Holding block button for "auto blocking" + if (Controls.KeyDown(Control.Block)) { - if (!Globals.Entities.TryGetValue(TargetIndex, out var foundEntity)) - { - foundEntity = TargetBox.MyEntity?.MapInstance?.Entities.FirstOrDefault(entity => entity.Id == TargetIndex) as Entity; - } - - if (foundEntity == default || foundEntity.IsHidden || foundEntity.IsStealthed) - { - ClearTarget(); - } + TryBlock(); } + } - TargetBox?.Update(); - StatusWindow?.Update(); - - // Hide our Guild window if we're not in a guild! - if (this == Globals.Me && string.IsNullOrEmpty(Guild) && Interface.Interface.GameUi != null) + if (TargetBox == default && this == Globals.Me && Interface.Interface.GameUi != default) + { + // If for WHATEVER reason the box hasn't been created, create it. + TargetBox = new EntityBox(Interface.Interface.GameUi.GameCanvas, EntityType.Player, null); + TargetBox.Hide(); + } + else if (TargetIndex != default) + { + if (!Globals.Entities.TryGetValue(TargetIndex, out var foundEntity)) { - Interface.Interface.GameUi.HideGuildWindow(); + foundEntity = TargetBox.MyEntity?.MapInstance?.Entities.FirstOrDefault(entity => entity.Id == TargetIndex) as Entity; } - if (IsBlocking && !IsAttacking && !IsMoving) + if (foundEntity == default || foundEntity.IsHidden || foundEntity.IsStealthed) { - IsBlocking = false; + ClearTarget(); } + } - var returnval = base.Update(); + TargetBox?.Update(); + StatusWindow?.Update(); - return returnval; + // Hide our Guild window if we're not in a guild! + if (this == Globals.Me && string.IsNullOrEmpty(Guild) && Interface.Interface.GameUi != null) + { + Interface.Interface.GameUi.HideGuildWindow(); } - //Loading - public override void Load(EntityPacket packet) + if (IsBlocking && !IsAttacking && !IsMoving) { - base.Load(packet); - var playerPacket = (PlayerEntityPacket)packet; - Gender = playerPacket.Gender; - Class = playerPacket.ClassId; - AccessLevel = playerPacket.AccessLevel; - CombatTimer = playerPacket.CombatTimeRemaining + Timing.Global.Milliseconds; - Guild = playerPacket.Guild; - Rank = playerPacket.GuildRank; + IsBlocking = false; + } - if (playerPacket.Equipment != null) - { - if (this == Globals.Me && playerPacket.Equipment.InventorySlots != null) - { - MyEquipment = playerPacket.Equipment.InventorySlots; - } - else if (playerPacket.Equipment.ItemIds != null) - { - Equipment = playerPacket.Equipment.ItemIds; - } - } + var returnval = base.Update(); - if (this == Globals.Me && TargetBox == null && Interface.Interface.GameUi != null) - { - TargetBox = new EntityBox(Interface.Interface.GameUi.GameCanvas, EntityType.Player, null); - TargetBox.Hide(); - } - } + return returnval; + } - //Item Processing - public void SwapItems(int fromSlotIndex, int toSlotIndex) - { - PacketSender.SendSwapInvItems(fromSlotIndex, toSlotIndex); - var fromSlot = Inventory[fromSlotIndex]; - var toSlot = Inventory[toSlotIndex]; + //Loading + public override void Load(EntityPacket packet) + { + base.Load(packet); + var playerPacket = (PlayerEntityPacket)packet; + Gender = playerPacket.Gender; + Class = playerPacket.ClassId; + AccessLevel = playerPacket.AccessLevel; + CombatTimer = playerPacket.CombatTimeRemaining + Timing.Global.Milliseconds; + Guild = playerPacket.Guild; + Rank = playerPacket.GuildRank; - if ( - fromSlot.ItemId == toSlot.ItemId - && ItemBase.TryGet(toSlot.ItemId, out var itemInSlot) - && itemInSlot.IsStackable - && fromSlot.Quantity < itemInSlot.MaxInventoryStack - && toSlot.Quantity < itemInSlot.MaxInventoryStack - ) + if (playerPacket.Equipment != null) + { + if (this == Globals.Me && playerPacket.Equipment.InventorySlots != null) { - var combinedQuantity = fromSlot.Quantity + toSlot.Quantity; - var toQuantity = Math.Min(itemInSlot.MaxInventoryStack, combinedQuantity); - var fromQuantity = combinedQuantity - toQuantity; - toSlot.Quantity = toQuantity; - fromSlot.Quantity = fromQuantity; - if (fromQuantity < 1) - { - Inventory[fromSlotIndex].ItemId = default; - } + MyEquipment = playerPacket.Equipment.InventorySlots; } - else + else if (playerPacket.Equipment.ItemIds != null) { - Inventory[fromSlotIndex] = toSlot; - Inventory[toSlotIndex] = fromSlot; + Equipment = playerPacket.Equipment.ItemIds; } } - public void TryDropItem(int inventorySlotIndex) + if (this == Globals.Me && TargetBox == null && Interface.Interface.GameUi != null) { - var inventorySlot = Inventory[inventorySlotIndex]; - if (!ItemBase.TryGet(inventorySlot.ItemId, out var itemDescriptor)) - { - return; - } - - var quantity = inventorySlot.Quantity; - var canDropMultiple = quantity > 1; - var inputType = canDropMultiple ? InputBox.InputType.NumericSliderInput : InputBox.InputType.YesNo; - var prompt = canDropMultiple ? Strings.Inventory.DropItemPrompt : Strings.Inventory.DropPrompt; - InputBox.Open( - title: Strings.Inventory.DropItemTitle, - prompt: prompt.ToString(itemDescriptor.Name), - modal: true, - inputType: inputType, - onSuccess: DropInputBoxOkay, - onCancel: default, - userData: inventorySlotIndex, - quantity: quantity, - maxQuantity: quantity - ); + TargetBox = new EntityBox(Interface.Interface.GameUi.GameCanvas, EntityType.Player, null); + TargetBox.Hide(); } + } - private void DropInputBoxOkay(object sender, EventArgs e) + //Item Processing + public void SwapItems(int fromSlotIndex, int toSlotIndex) + { + PacketSender.SendSwapInvItems(fromSlotIndex, toSlotIndex); + var fromSlot = Inventory[fromSlotIndex]; + var toSlot = Inventory[toSlotIndex]; + + if ( + fromSlot.ItemId == toSlot.ItemId + && ItemBase.TryGet(toSlot.ItemId, out var itemInSlot) + && itemInSlot.IsStackable + && fromSlot.Quantity < itemInSlot.MaxInventoryStack + && toSlot.Quantity < itemInSlot.MaxInventoryStack + ) { - var value = (int)Math.Round(((InputBox)sender).Value); - if (value > 0) + var combinedQuantity = fromSlot.Quantity + toSlot.Quantity; + var toQuantity = Math.Min(itemInSlot.MaxInventoryStack, combinedQuantity); + var fromQuantity = combinedQuantity - toQuantity; + toSlot.Quantity = toQuantity; + fromSlot.Quantity = fromQuantity; + if (fromQuantity < 1) { - PacketSender.SendDropItem((int)((InputBox)sender).UserData, value); + Inventory[fromSlotIndex].ItemId = default; } } - - public int FindItem(Guid itemId, int itemVal = 1) + else { - for (var i = 0; i < Options.MaxInvItems; i++) - { - if (Inventory[i].ItemId == itemId && Inventory[i].Quantity >= itemVal) - { - return i; - } - } - - return -1; + Inventory[fromSlotIndex] = toSlot; + Inventory[toSlotIndex] = fromSlot; } + } + + public void TryDropItem(int inventorySlotIndex) + { + var inventorySlot = Inventory[inventorySlotIndex]; + if (!ItemBase.TryGet(inventorySlot.ItemId, out var itemDescriptor)) + { + return; + } + + var quantity = inventorySlot.Quantity; + var canDropMultiple = quantity > 1; + var inputType = canDropMultiple ? InputBox.InputType.NumericSliderInput : InputBox.InputType.YesNo; + var prompt = canDropMultiple ? Strings.Inventory.DropItemPrompt : Strings.Inventory.DropPrompt; + InputBox.Open( + title: Strings.Inventory.DropItemTitle, + prompt: prompt.ToString(itemDescriptor.Name), + modal: true, + inputType: inputType, + onSuccess: DropInputBoxOkay, + onCancel: default, + userData: inventorySlotIndex, + quantity: quantity, + maxQuantity: quantity + ); + } - private int GetQuantityOfItemIn(IEnumerable items, Guid itemId) + private void DropInputBoxOkay(object sender, EventArgs e) + { + var value = (int)Math.Round(((InputBox)sender).Value); + if (value > 0) { - long count = 0; + PacketSender.SendDropItem((int)((InputBox)sender).UserData, value); + } + } - foreach (var slot in (items ?? Enumerable.Empty())) + public int FindItem(Guid itemId, int itemVal = 1) + { + for (var i = 0; i < Options.MaxInvItems; i++) + { + if (Inventory[i].ItemId == itemId && Inventory[i].Quantity >= itemVal) { - if (slot?.ItemId == itemId) - { - count += slot.Quantity; - } + return i; } - - return (int)Math.Min(count, int.MaxValue); } - public int GetQuantityOfItemInBank(Guid itemId) => GetQuantityOfItemIn(Globals.Bank, itemId); + return -1; + } - public int GetQuantityOfItemInInventory(Guid itemId) => GetQuantityOfItemIn(Inventory, itemId); + private int GetQuantityOfItemIn(IEnumerable items, Guid itemId) + { + long count = 0; - public void TryUseItem(int index) + foreach (var slot in (items ?? Enumerable.Empty())) { - if (!IsItemOnCooldown(index) && - index >= 0 && index < Globals.Me.Inventory.Length && Globals.Me.Inventory[index]?.Quantity > 0) + if (slot?.ItemId == itemId) { - PacketSender.SendUseItem(index, TargetIndex); + count += slot.Quantity; } } - public long GetItemCooldown(Guid id) - { - if (ItemCooldowns.ContainsKey(id)) - { - return ItemCooldowns[id]; - } + return (int)Math.Min(count, int.MaxValue); + } - return 0; + public int GetQuantityOfItemInBank(Guid itemId) => GetQuantityOfItemIn(Globals.Bank, itemId); + + public int GetQuantityOfItemInInventory(Guid itemId) => GetQuantityOfItemIn(Inventory, itemId); + + public void TryUseItem(int index) + { + if (!IsItemOnCooldown(index) && + index >= 0 && index < Globals.Me.Inventory.Length && Globals.Me.Inventory[index]?.Quantity > 0) + { + PacketSender.SendUseItem(index, TargetIndex); } + } - public int FindHotbarItem(IHotbarInstance hotbarInstance) + public long GetItemCooldown(Guid id) + { + if (ItemCooldowns.ContainsKey(id)) { - var bestMatch = -1; + return ItemCooldowns[id]; + } + + return 0; + } + + public int FindHotbarItem(IHotbarInstance hotbarInstance) + { + var bestMatch = -1; - if (hotbarInstance.ItemOrSpellId != Guid.Empty) + if (hotbarInstance.ItemOrSpellId != Guid.Empty) + { + for (var i = 0; i < Inventory.Length; i++) { - for (var i = 0; i < Inventory.Length; i++) + var itm = Inventory[i]; + if (itm != null && itm.ItemId == hotbarInstance.ItemOrSpellId) { - var itm = Inventory[i]; - if (itm != null && itm.ItemId == hotbarInstance.ItemOrSpellId) + bestMatch = i; + var itemBase = ItemBase.Get(itm.ItemId); + if (itemBase != null) { - bestMatch = i; - var itemBase = ItemBase.Get(itm.ItemId); - if (itemBase != null) + if (itemBase.ItemType == ItemType.Bag) { - if (itemBase.ItemType == ItemType.Bag) + if (hotbarInstance.BagId == itm.BagId) { - if (hotbarInstance.BagId == itm.BagId) - { - break; - } + break; } - else if (itemBase.ItemType == ItemType.Equipment) + } + else if (itemBase.ItemType == ItemType.Equipment) + { + if (hotbarInstance.PreferredStatBuffs != null) { - if (hotbarInstance.PreferredStatBuffs != null) + var statMatch = true; + for (var s = 0; s < hotbarInstance.PreferredStatBuffs.Length; s++) { - var statMatch = true; - for (var s = 0; s < hotbarInstance.PreferredStatBuffs.Length; s++) + if (itm.ItemProperties.StatModifiers[s] != hotbarInstance.PreferredStatBuffs[s]) { - if (itm.ItemProperties.StatModifiers[s] != hotbarInstance.PreferredStatBuffs[s]) - { - statMatch = false; - } + statMatch = false; } + } - if (statMatch) - { - break; - } + if (statMatch) + { + break; } } - else - { - break; - } + } + else + { + break; } } } } + } - return bestMatch; + return bestMatch; + } + + public bool IsEquipped(int slot) + { + for (var i = 0; i < Options.EquipmentSlots.Count; i++) + { + if (MyEquipment[i] == slot) + { + return true; + } } - public bool IsEquipped(int slot) + return false; + } + + public bool IsItemOnCooldown(int slot) + { + if (Inventory[slot] != null) { - for (var i = 0; i < Options.EquipmentSlots.Count; i++) + var itm = Inventory[slot]; + if (itm.ItemId != Guid.Empty) { - if (MyEquipment[i] == slot) + if (ItemCooldowns.ContainsKey(itm.ItemId) && ItemCooldowns[itm.ItemId] > Timing.Global.Milliseconds) { return true; } - } - return false; + if ((ItemBase.TryGet(itm.ItemId, out var itemBase) && !itemBase.IgnoreGlobalCooldown) && Globals.Me.GlobalCooldown > Timing.Global.Milliseconds) + { + return true; + } + } } - public bool IsItemOnCooldown(int slot) + return false; + } + + public long GetItemRemainingCooldown(int slot) + { + if (Inventory[slot] != null) { - if (Inventory[slot] != null) + var itm = Inventory[slot]; + if (itm.ItemId != Guid.Empty) { - var itm = Inventory[slot]; - if (itm.ItemId != Guid.Empty) + if (ItemCooldowns.ContainsKey(itm.ItemId) && ItemCooldowns[itm.ItemId] > Timing.Global.Milliseconds) { - if (ItemCooldowns.ContainsKey(itm.ItemId) && ItemCooldowns[itm.ItemId] > Timing.Global.Milliseconds) - { - return true; - } + return ItemCooldowns[itm.ItemId] - Timing.Global.Milliseconds; + } - if ((ItemBase.TryGet(itm.ItemId, out var itemBase) && !itemBase.IgnoreGlobalCooldown) && Globals.Me.GlobalCooldown > Timing.Global.Milliseconds) - { - return true; - } + if ((ItemBase.TryGet(itm.ItemId, out var itemBase) && !itemBase.IgnoreGlobalCooldown) && Globals.Me.GlobalCooldown > Timing.Global.Milliseconds) + { + return Globals.Me.GlobalCooldown - Timing.Global.Milliseconds; } } - - return false; } - public long GetItemRemainingCooldown(int slot) + return 0; + } + + public bool IsSpellOnCooldown(int slot) + { + if (Spells[slot] != null) { - if (Inventory[slot] != null) + var spl = Spells[slot]; + if (spl.Id != Guid.Empty) { - var itm = Inventory[slot]; - if (itm.ItemId != Guid.Empty) + if (SpellCooldowns.ContainsKey(spl.Id) && SpellCooldowns[spl.Id] > Timing.Global.Milliseconds) { - if (ItemCooldowns.ContainsKey(itm.ItemId) && ItemCooldowns[itm.ItemId] > Timing.Global.Milliseconds) - { - return ItemCooldowns[itm.ItemId] - Timing.Global.Milliseconds; - } + return true; + } - if ((ItemBase.TryGet(itm.ItemId, out var itemBase) && !itemBase.IgnoreGlobalCooldown) && Globals.Me.GlobalCooldown > Timing.Global.Milliseconds) - { - return Globals.Me.GlobalCooldown - Timing.Global.Milliseconds; - } + if ((SpellBase.TryGet(spl.Id, out var spellBase) && !spellBase.IgnoreGlobalCooldown) && Globals.Me.GlobalCooldown > Timing.Global.Milliseconds) + { + return true; } } + } + + return false; + } + public long GetSpellRemainingCooldown(int slot) + { + if (slot < 0 || Spells.Length <= slot) + { + Log.Warn(new ArgumentOutOfRangeException(nameof(slot), slot, $@"Slot was out of the range [0,{Spells.Length}")); return 0; } - public bool IsSpellOnCooldown(int slot) + var spell = Spells[slot]; + // These two can't be combined into a nullish expression because Guid is a struct + if (spell == default || spell.Id == Guid.Empty) { - if (Spells[slot] != null) - { - var spl = Spells[slot]; - if (spl.Id != Guid.Empty) - { - if (SpellCooldowns.ContainsKey(spl.Id) && SpellCooldowns[spl.Id] > Timing.Global.Milliseconds) - { - return true; - } + return 0; + } - if ((SpellBase.TryGet(spl.Id, out var spellBase) && !spellBase.IgnoreGlobalCooldown) && Globals.Me.GlobalCooldown > Timing.Global.Milliseconds) - { - return true; - } - } - } + var now = Timing.Global.Milliseconds; - return false; + if (SpellCooldowns.TryGetValue(spell.Id, out var cd) && cd > now) + { + return cd - now; } - public long GetSpellRemainingCooldown(int slot) + if (SpellBase.TryGet(spell.Id, out var spellBase) && !spellBase.IgnoreGlobalCooldown && Globals.Me.GlobalCooldown > now) { - if (slot < 0 || Spells.Length <= slot) - { - Log.Warn(new ArgumentOutOfRangeException(nameof(slot), slot, $@"Slot was out of the range [0,{Spells.Length}")); - return 0; - } + return Globals.Me.GlobalCooldown - now; + } - var spell = Spells[slot]; - // These two can't be combined into a nullish expression because Guid is a struct - if (spell == default || spell.Id == Guid.Empty) - { - return 0; - } + return 0; + } - var now = Timing.Global.Milliseconds; + public void TrySellItem(int inventorySlotIndex) + { + var inventorySlot = Inventory[inventorySlotIndex]; + if (!ItemBase.TryGet(inventorySlot.ItemId, out var itemDescriptor)) + { + return; + } - if (SpellCooldowns.TryGetValue(spell.Id, out var cd) && cd > now) - { - return cd - now; - } + var shop = Globals.GameShop; + var shopCanBuyItem = + shop.BuyingWhitelist && shop.BuyingItems.Any(buyingItem => buyingItem.ItemId == itemDescriptor.Id) + || !shop.BuyingWhitelist && !shop.BuyingItems.Any(buyingItem => buyingItem.ItemId == itemDescriptor.Id); - if (SpellBase.TryGet(spell.Id, out var spellBase) && !spellBase.IgnoreGlobalCooldown && Globals.Me.GlobalCooldown > now) - { - return Globals.Me.GlobalCooldown - now; - } + var prompt = Strings.Shop.SellPrompt; + var inputType = InputBox.InputType.YesNo; + EventHandler onSuccess = SellInputBoxOkay; + var userData = inventorySlotIndex; + var slotQuantity = inventorySlot.Quantity; + var maxQuantity = slotQuantity; - return 0; + if (!shopCanBuyItem) + { + prompt = Strings.Shop.CannotSell; + inputType = InputBox.InputType.OkayOnly; + onSuccess = null; + userData = -1; } - - public void TrySellItem(int inventorySlotIndex) + else if (itemDescriptor.IsStackable || slotQuantity > 1) { - var inventorySlot = Inventory[inventorySlotIndex]; - if (!ItemBase.TryGet(inventorySlot.ItemId, out var itemDescriptor)) + var inventoryQuantity = GetQuantityOfItemInInventory(itemDescriptor.Id); + if (inventoryQuantity > 1) { - return; + maxQuantity = inventoryQuantity; + prompt = Strings.Shop.SellItemPrompt; + inputType = InputBox.InputType.NumericSliderInput; + onSuccess = SellItemInputBoxOkay; + userData = inventorySlotIndex; } + } - var shop = Globals.GameShop; - var shopCanBuyItem = - shop.BuyingWhitelist && shop.BuyingItems.Any(buyingItem => buyingItem.ItemId == itemDescriptor.Id) - || !shop.BuyingWhitelist && !shop.BuyingItems.Any(buyingItem => buyingItem.ItemId == itemDescriptor.Id); - - var prompt = Strings.Shop.SellPrompt; - var inputType = InputBox.InputType.YesNo; - EventHandler onSuccess = SellInputBoxOkay; - var userData = inventorySlotIndex; - var slotQuantity = inventorySlot.Quantity; - var maxQuantity = slotQuantity; - - if (!shopCanBuyItem) - { - prompt = Strings.Shop.CannotSell; - inputType = InputBox.InputType.OkayOnly; - onSuccess = null; - userData = -1; - } - else if (itemDescriptor.IsStackable || slotQuantity > 1) - { - var inventoryQuantity = GetQuantityOfItemInInventory(itemDescriptor.Id); - if (inventoryQuantity > 1) - { - maxQuantity = inventoryQuantity; - prompt = Strings.Shop.SellItemPrompt; - inputType = InputBox.InputType.NumericSliderInput; - onSuccess = SellItemInputBoxOkay; - userData = inventorySlotIndex; - } - } + InputBox.Open( + title: Strings.Shop.SellItem, + prompt: prompt.ToString(itemDescriptor.Name), + modal: true, + inputType: inputType, + onSuccess: onSuccess, + onCancel: null, + userData: userData, + quantity: slotQuantity, + maxQuantity: maxQuantity + ); + } - InputBox.Open( - title: Strings.Shop.SellItem, - prompt: prompt.ToString(itemDescriptor.Name), - modal: true, - inputType: inputType, - onSuccess: onSuccess, - onCancel: null, - userData: userData, - quantity: slotQuantity, - maxQuantity: maxQuantity - ); + public void TryBuyItem(int shopSlotIndex) + { + //Confirm the purchase + var shopSlot = Globals.GameShop.SellingItems[shopSlotIndex]; + if (!ItemBase.TryGet(shopSlot.ItemId, out var itemDescriptor)) + { + return; } - public void TryBuyItem(int shopSlotIndex) + var maxBuyAmount = 0; + if (shopSlot.CostItemQuantity < 1) { - //Confirm the purchase - var shopSlot = Globals.GameShop.SellingItems[shopSlotIndex]; - if (!ItemBase.TryGet(shopSlot.ItemId, out var itemDescriptor)) - { - return; - } + var emptySlots = Inventory.Count(inventorySlot => inventorySlot.ItemId == default); + var slotsWithItem = Inventory.Count(inventorySlot => inventorySlot.ItemId == itemDescriptor.Id); + var currentItemQuantity = GetQuantityOfItemInInventory(shopSlot.ItemId); + var stackSize = itemDescriptor.IsStackable ? itemDescriptor.MaxInventoryStack : 1; + var itemQuantityLimitInCurrentStacks = slotsWithItem * stackSize; + var partialStackEmptyQuantity = itemQuantityLimitInCurrentStacks - currentItemQuantity; + maxBuyAmount = emptySlots * stackSize + partialStackEmptyQuantity; + } + else + { + var currencyCount = GetQuantityOfItemInInventory(shopSlot.CostItemId); + maxBuyAmount = (int)Math.Floor(currencyCount / (float)shopSlot.CostItemQuantity); + } - var maxBuyAmount = 0; - if (shopSlot.CostItemQuantity < 1) - { - var emptySlots = Inventory.Count(inventorySlot => inventorySlot.ItemId == default); - var slotsWithItem = Inventory.Count(inventorySlot => inventorySlot.ItemId == itemDescriptor.Id); - var currentItemQuantity = GetQuantityOfItemInInventory(shopSlot.ItemId); - var stackSize = itemDescriptor.IsStackable ? itemDescriptor.MaxInventoryStack : 1; - var itemQuantityLimitInCurrentStacks = slotsWithItem * stackSize; - var partialStackEmptyQuantity = itemQuantityLimitInCurrentStacks - currentItemQuantity; - maxBuyAmount = emptySlots * stackSize + partialStackEmptyQuantity; - } - else - { - var currencyCount = GetQuantityOfItemInInventory(shopSlot.CostItemId); - maxBuyAmount = (int)Math.Floor(currencyCount / (float)shopSlot.CostItemQuantity); - } + // If our max buy amount is 0 or the item isn't stackable, let the server handle it + if (!itemDescriptor.IsStackable || maxBuyAmount == 0) + { + PacketSender.SendBuyItem(shopSlotIndex, 1); + return; + } - // If our max buy amount is 0 or the item isn't stackable, let the server handle it - if (!itemDescriptor.IsStackable || maxBuyAmount == 0) - { - PacketSender.SendBuyItem(shopSlotIndex, 1); - return; - } + InputBox.Open( + title: Strings.Shop.BuyItem, + prompt: Strings.Shop.BuyItemPrompt.ToString(itemDescriptor.Name), + modal: true, + inputType: InputBox.InputType.NumericSliderInput, + onSuccess: BuyItemInputBoxOkay, + onCancel: null, + userData: shopSlotIndex, + quantity: maxBuyAmount, + maxQuantity: maxBuyAmount + ); + } - InputBox.Open( - title: Strings.Shop.BuyItem, - prompt: Strings.Shop.BuyItemPrompt.ToString(itemDescriptor.Name), - modal: true, - inputType: InputBox.InputType.NumericSliderInput, - onSuccess: BuyItemInputBoxOkay, - onCancel: null, - userData: shopSlotIndex, - quantity: maxBuyAmount, - maxQuantity: maxBuyAmount - ); + private void BuyItemInputBoxOkay(object sender, EventArgs e) + { + var value = (int)Math.Round(((InputBox)sender).Value); + if (value > 0) + { + PacketSender.SendBuyItem((int)((InputBox)sender).UserData, value); } + } - private void BuyItemInputBoxOkay(object sender, EventArgs e) + private void SellItemInputBoxOkay(object sender, EventArgs e) + { + var value = (int)Math.Round(((InputBox)sender).Value); + if (value > 0) { - var value = (int)Math.Round(((InputBox)sender).Value); - if (value > 0) - { - PacketSender.SendBuyItem((int)((InputBox)sender).UserData, value); - } + PacketSender.SendSellItem((int)((InputBox)sender).UserData, value); } + } - private void SellItemInputBoxOkay(object sender, EventArgs e) + private void SellInputBoxOkay(object sender, EventArgs e) + { + PacketSender.SendSellItem((int)((InputBox)sender).UserData, 1); + } + + /// + /// Attempts to deposit the item from the inventory into the bank. + /// + /// + /// + /// + /// + /// + /// + public bool TryDepositItem( + int inventorySlotIndex, + IItem? slot = null, + int bankSlotIndex = -1, + int quantityHint = -1, + bool skipPrompt = false + ) + { + // Permission Check for Guild Bank + if (Globals.GuildBank && !IsGuildBankDepositAllowed()) { - var value = (int)Math.Round(((InputBox)sender).Value); - if (value > 0) - { - PacketSender.SendSellItem((int)((InputBox)sender).UserData, value); - } + ChatboxMsg.AddMessage(new ChatboxMsg(Strings.Guilds.NotAllowedDeposit.ToString(Globals.Me.Guild), CustomColors.Alerts.Error, ChatMessageType.Bank)); + return false; } - private void SellInputBoxOkay(object sender, EventArgs e) + slot ??= Inventory[inventorySlotIndex]; + if (!ItemBase.TryGet(slot.ItemId, out var itemDescriptor)) { - PacketSender.SendSellItem((int)((InputBox)sender).UserData, 1); + Log.Warn($"Tried to move item that does not exist from slot {inventorySlotIndex}: {itemDescriptor.Id}"); + return false; } - /// - /// Attempts to deposit the item from the inventory into the bank. - /// - /// - /// - /// - /// - /// - /// - public bool TryDepositItem( - int inventorySlotIndex, - IItem? slot = null, - int bankSlotIndex = -1, - int quantityHint = -1, - bool skipPrompt = false - ) + // ReSharper disable once ConvertIfStatementToSwitchStatement + if (quantityHint == 0) { - // Permission Check for Guild Bank - if (Globals.GuildBank && !IsGuildBankDepositAllowed()) - { - ChatboxMsg.AddMessage(new ChatboxMsg(Strings.Guilds.NotAllowedDeposit.ToString(Globals.Me.Guild), CustomColors.Alerts.Error, ChatMessageType.Bank)); - return false; - } + Log.Warn($"Tried to move 0 of '{itemDescriptor.Name}' ({itemDescriptor.Id})"); + return false; + } - slot ??= Inventory[inventorySlotIndex]; - if (!ItemBase.TryGet(slot.ItemId, out var itemDescriptor)) - { - Log.Warn($"Tried to move item that does not exist from slot {inventorySlotIndex}: {itemDescriptor.Id}"); - return false; - } + var maximumStack = itemDescriptor.Stackable ? itemDescriptor.MaxBankStack : 1; + var sourceQuantity = GetQuantityOfItemInInventory(itemDescriptor.Id); + var quantity = quantityHint < 0 ? sourceQuantity : quantityHint; - // ReSharper disable once ConvertIfStatementToSwitchStatement - if (quantityHint == 0) - { - Log.Warn($"Tried to move 0 of '{itemDescriptor.Name}' ({itemDescriptor.Id})"); - return false; - } + var targetSlots = Globals.Bank.ToArray(); - var maximumStack = itemDescriptor.Stackable ? itemDescriptor.MaxBankStack : 1; - var sourceQuantity = GetQuantityOfItemInInventory(itemDescriptor.Id); - var quantity = quantityHint < 0 ? sourceQuantity : quantityHint; + var movableQuantity = Item.FindSpaceForItem( + itemDescriptor.Id, + itemDescriptor.ItemType, + maximumStack, + bankSlotIndex, + quantityHint < 0 ? sourceQuantity : quantityHint, + targetSlots + ); - var targetSlots = Globals.Bank.ToArray(); + if (movableQuantity < 1) + { + ChatboxMsg.AddMessage(new ChatboxMsg( + Strings.Bank.NoSpace, + CustomColors.Alerts.Error, + ChatMessageType.Bank + )); + return false; + } - var movableQuantity = Item.FindSpaceForItem( - itemDescriptor.Id, - itemDescriptor.ItemType, - maximumStack, - bankSlotIndex, - quantityHint < 0 ? sourceQuantity : quantityHint, - targetSlots - ); + if (bankSlotIndex < 0 && itemDescriptor.IsStackable) + { + bankSlotIndex = Item.FindFirstPartialSlot(itemDescriptor.Id, targetSlots, maximumStack); + } - if (movableQuantity < 1) - { - ChatboxMsg.AddMessage(new ChatboxMsg( - Strings.Bank.NoSpace, - CustomColors.Alerts.Error, - ChatMessageType.Bank - )); - return false; - } + if (skipPrompt) + { + PacketSender.SendDepositItem(inventorySlotIndex, movableQuantity, bankSlotIndex); + return true; + } - if (bankSlotIndex < 0 && itemDescriptor.IsStackable) - { - bankSlotIndex = Item.FindFirstPartialSlot(itemDescriptor.Id, targetSlots, maximumStack); - } + var maximumQuantity = movableQuantity < quantity ? movableQuantity : Item.FindSpaceForItem( + itemDescriptor.Id, + itemDescriptor.ItemType, + maximumStack, + bankSlotIndex, + sourceQuantity, + targetSlots + ); - if (skipPrompt) - { - PacketSender.SendDepositItem(inventorySlotIndex, movableQuantity, bankSlotIndex); - return true; - } + if (maximumQuantity == 1) + { + PacketSender.SendDepositItem(inventorySlotIndex, movableQuantity, bankSlotIndex); + return true; + } - var maximumQuantity = movableQuantity < quantity ? movableQuantity : Item.FindSpaceForItem( - itemDescriptor.Id, - itemDescriptor.ItemType, - maximumStack, - bankSlotIndex, - sourceQuantity, - targetSlots - ); + InputBox.Open( + title: Strings.Bank.DepositItem, + prompt: Strings.Bank.DepositItemPrompt.ToString(itemDescriptor.Name), + modal: true, + inputType: InputBox.InputType.NumericSliderInput, + onSuccess: DepositItemInputBoxOkay, + onCancel: null, + userData: new[] { inventorySlotIndex, bankSlotIndex }, + quantity: movableQuantity, + maxQuantity: maximumQuantity + ); - if (maximumQuantity == 1) - { - PacketSender.SendDepositItem(inventorySlotIndex, movableQuantity, bankSlotIndex); - return true; - } + return true; + } - InputBox.Open( - title: Strings.Bank.DepositItem, - prompt: Strings.Bank.DepositItemPrompt.ToString(itemDescriptor.Name), - modal: true, - inputType: InputBox.InputType.NumericSliderInput, - onSuccess: DepositItemInputBoxOkay, - onCancel: null, - userData: new[] { inventorySlotIndex, bankSlotIndex }, - quantity: movableQuantity, - maxQuantity: maximumQuantity - ); + private bool IsGuildBankDepositAllowed() + { + return !string.IsNullOrWhiteSpace(Globals.Me.Guild) && + (Globals.Me.GuildRank.Permissions.BankDeposit || Globals.Me.Rank == 0); + } - return true; + private void DepositItemInputBoxOkay(object sender, EventArgs e) + { + var value = (int)Math.Round(((InputBox)sender).Value); + if (value > 0) + { + var userData = (int[])((InputBox)sender).UserData; + + PacketSender.SendDepositItem(userData[0], value, userData[1]); } + } - private bool IsGuildBankDepositAllowed() + /// + /// Attempts to withdraw items from the bank into the inventory. + /// + /// + /// + /// + /// + /// + /// + public bool TryWithdrawItem( + int bankSlotIndex, + IItem? slot = null, + int inventorySlotIndex = -1, + int quantityHint = -1, + bool skipPrompt = false + ) + { + // Permission Check for Guild Bank + if (Globals.GuildBank && !IsGuildBankWithdrawAllowed()) { - return !string.IsNullOrWhiteSpace(Globals.Me.Guild) && - (Globals.Me.GuildRank.Permissions.BankDeposit || Globals.Me.Rank == 0); + ChatboxMsg.AddMessage(new ChatboxMsg(Strings.Guilds.NotAllowedWithdraw.ToString(Globals.Me.Guild), CustomColors.Alerts.Error, ChatMessageType.Bank)); + return false; } - private void DepositItemInputBoxOkay(object sender, EventArgs e) + slot ??= Globals.Bank[bankSlotIndex]; + if (!ItemBase.TryGet(slot.ItemId, out var itemDescriptor)) { - var value = (int)Math.Round(((InputBox)sender).Value); - if (value > 0) - { - var userData = (int[])((InputBox)sender).UserData; - - PacketSender.SendDepositItem(userData[0], value, userData[1]); - } + Log.Warn($"Tried to move item that does not exist from slot {bankSlotIndex}: {itemDescriptor.Id}"); + return false; } - /// - /// Attempts to withdraw items from the bank into the inventory. - /// - /// - /// - /// - /// - /// - /// - public bool TryWithdrawItem( - int bankSlotIndex, - IItem? slot = null, - int inventorySlotIndex = -1, - int quantityHint = -1, - bool skipPrompt = false - ) + // ReSharper disable once ConvertIfStatementToSwitchStatement + if (quantityHint == 0) { - // Permission Check for Guild Bank - if (Globals.GuildBank && !IsGuildBankWithdrawAllowed()) - { - ChatboxMsg.AddMessage(new ChatboxMsg(Strings.Guilds.NotAllowedWithdraw.ToString(Globals.Me.Guild), CustomColors.Alerts.Error, ChatMessageType.Bank)); - return false; - } - - slot ??= Globals.Bank[bankSlotIndex]; - if (!ItemBase.TryGet(slot.ItemId, out var itemDescriptor)) - { - Log.Warn($"Tried to move item that does not exist from slot {bankSlotIndex}: {itemDescriptor.Id}"); - return false; - } + Log.Warn($"Tried to move 0 of '{itemDescriptor.Name}' ({itemDescriptor.Id})"); + return false; + } - // ReSharper disable once ConvertIfStatementToSwitchStatement - if (quantityHint == 0) - { - Log.Warn($"Tried to move 0 of '{itemDescriptor.Name}' ({itemDescriptor.Id})"); - return false; - } + var maximumStack = itemDescriptor.Stackable ? itemDescriptor.MaxInventoryStack : 1; + var sourceQuantity = GetQuantityOfItemInBank(itemDescriptor.Id); + var quantity = quantityHint < 0 ? sourceQuantity : quantityHint; + var targetSlots = Inventory.ToArray(); - var maximumStack = itemDescriptor.Stackable ? itemDescriptor.MaxInventoryStack : 1; - var sourceQuantity = GetQuantityOfItemInBank(itemDescriptor.Id); - var quantity = quantityHint < 0 ? sourceQuantity : quantityHint; - var targetSlots = Inventory.ToArray(); + var movableQuantity = Item.FindSpaceForItem( + itemDescriptor.Id, + itemDescriptor.ItemType, + maximumStack, + bankSlotIndex, + quantityHint < 0 ? sourceQuantity : quantityHint, + targetSlots + ); - var movableQuantity = Item.FindSpaceForItem( - itemDescriptor.Id, - itemDescriptor.ItemType, - maximumStack, - bankSlotIndex, - quantityHint < 0 ? sourceQuantity : quantityHint, - targetSlots - ); + if (movableQuantity < 1) + { + ChatboxMsg.AddMessage(new ChatboxMsg( + Strings.Bank.WithdrawItemNoSpace, + CustomColors.Alerts.Error, + ChatMessageType.Bank + )); + return false; + } - if (movableQuantity < 1) - { - ChatboxMsg.AddMessage(new ChatboxMsg( - Strings.Bank.WithdrawItemNoSpace, - CustomColors.Alerts.Error, - ChatMessageType.Bank - )); - return false; - } + if (inventorySlotIndex < 0 && itemDescriptor.IsStackable) + { + inventorySlotIndex = Item.FindFirstPartialSlot(itemDescriptor.Id, targetSlots, maximumStack); + } - if (inventorySlotIndex < 0 && itemDescriptor.IsStackable) - { - inventorySlotIndex = Item.FindFirstPartialSlot(itemDescriptor.Id, targetSlots, maximumStack); - } + if (skipPrompt) + { + PacketSender.SendWithdrawItem(bankSlotIndex, movableQuantity, inventorySlotIndex); + return true; + } - if (skipPrompt) - { - PacketSender.SendWithdrawItem(bankSlotIndex, movableQuantity, inventorySlotIndex); - return true; - } + var maximumQuantity = movableQuantity < quantity ? movableQuantity : Item.FindSpaceForItem( + itemDescriptor.Id, + itemDescriptor.ItemType, + maximumStack, + inventorySlotIndex, + sourceQuantity, + targetSlots + ); - var maximumQuantity = movableQuantity < quantity ? movableQuantity : Item.FindSpaceForItem( - itemDescriptor.Id, - itemDescriptor.ItemType, - maximumStack, - inventorySlotIndex, - sourceQuantity, - targetSlots - ); + if (maximumQuantity == 1) + { + PacketSender.SendWithdrawItem(bankSlotIndex, movableQuantity, inventorySlotIndex); + return true; + } - if (maximumQuantity == 1) - { - PacketSender.SendWithdrawItem(bankSlotIndex, movableQuantity, inventorySlotIndex); - return true; - } + InputBox.Open( + title: Strings.Bank.WithdrawItem, + prompt: Strings.Bank.WithdrawItemPrompt.ToString(itemDescriptor.Name), + modal: true, + inputType: InputBox.InputType.NumericSliderInput, + onSuccess: WithdrawItemInputBoxOkay, + onCancel: null, + userData: new[] { bankSlotIndex, inventorySlotIndex }, + quantity: movableQuantity, + maxQuantity: maximumQuantity + ); - InputBox.Open( - title: Strings.Bank.WithdrawItem, - prompt: Strings.Bank.WithdrawItemPrompt.ToString(itemDescriptor.Name), - modal: true, - inputType: InputBox.InputType.NumericSliderInput, - onSuccess: WithdrawItemInputBoxOkay, - onCancel: null, - userData: new[] { bankSlotIndex, inventorySlotIndex }, - quantity: movableQuantity, - maxQuantity: maximumQuantity - ); + return true; + } - return true; - } + private bool IsGuildBankWithdrawAllowed() + { + return !string.IsNullOrWhiteSpace(Globals.Me.Guild) && + (Globals.Me.GuildRank.Permissions.BankRetrieve || Globals.Me.Rank == 0); + } - private bool IsGuildBankWithdrawAllowed() + private void WithdrawItemInputBoxOkay(object sender, EventArgs e) + { + var value = (int)Math.Round(((InputBox)sender).Value); + if (value > 0) { - return !string.IsNullOrWhiteSpace(Globals.Me.Guild) && - (Globals.Me.GuildRank.Permissions.BankRetrieve || Globals.Me.Rank == 0); + int[] userData = (int[])((InputBox)sender).UserData; + PacketSender.SendWithdrawItem(userData[0], value, userData[1]); } + } - private void WithdrawItemInputBoxOkay(object sender, EventArgs e) + //Bag + public void TryStoreBagItem(int inventorySlotIndex, int bagSlotIndex) + { + var inventorySlot = Inventory[inventorySlotIndex]; + if (!ItemBase.TryGet(inventorySlot.ItemId, out var itemDescriptor)) { - var value = (int)Math.Round(((InputBox)sender).Value); - if (value > 0) - { - int[] userData = (int[])((InputBox)sender).UserData; - PacketSender.SendWithdrawItem(userData[0], value, userData[1]); - } + return; } - //Bag - public void TryStoreBagItem(int inventorySlotIndex, int bagSlotIndex) - { - var inventorySlot = Inventory[inventorySlotIndex]; - if (!ItemBase.TryGet(inventorySlot.ItemId, out var itemDescriptor)) - { - return; - } + int[] userData = new int[2] { inventorySlotIndex, bagSlotIndex }; - int[] userData = new int[2] { inventorySlotIndex, bagSlotIndex }; + var quantity = inventorySlot.Quantity; + var maxQuantity = quantity; - var quantity = inventorySlot.Quantity; - var maxQuantity = quantity; + // TODO: Refactor server bagging logic to allow transferring quantities from the entire inventory and not just the slot + //if (itemDescriptor.IsStackable) + //{ + // maxQuantity = GetQuantityOfItemInInventory(itemDescriptor.Id); + //} - // TODO: Refactor server bagging logic to allow transferring quantities from the entire inventory and not just the slot - //if (itemDescriptor.IsStackable) - //{ - // maxQuantity = GetQuantityOfItemInInventory(itemDescriptor.Id); - //} + if (maxQuantity < 2) + { + PacketSender.SendStoreBagItem(inventorySlotIndex, 1, bagSlotIndex); + return; + } - if (maxQuantity < 2) - { - PacketSender.SendStoreBagItem(inventorySlotIndex, 1, bagSlotIndex); - return; - } + InputBox.Open( + title: Strings.Bags.StoreItem, + prompt: Strings.Bags.StoreItemPrompt.ToString(itemDescriptor.Name), true, + inputType: InputBox.InputType.NumericSliderInput, + onSuccess: StoreBagItemInputBoxOkay, + onCancel: null, + userData: userData, + quantity: quantity, + maxQuantity: maxQuantity + ); + } - InputBox.Open( - title: Strings.Bags.StoreItem, - prompt: Strings.Bags.StoreItemPrompt.ToString(itemDescriptor.Name), true, - inputType: InputBox.InputType.NumericSliderInput, - onSuccess: StoreBagItemInputBoxOkay, - onCancel: null, - userData: userData, - quantity: quantity, - maxQuantity: maxQuantity - ); + private void StoreBagItemInputBoxOkay(object sender, EventArgs e) + { + var value = (int)Math.Round(((InputBox)sender).Value); + if (value > 0) + { + int[] userData = (int[])((InputBox)sender).UserData; + PacketSender.SendStoreBagItem(userData[0], value, userData[1]); } + } - private void StoreBagItemInputBoxOkay(object sender, EventArgs e) + public void TryRetreiveBagItem(int bagSlotIndex, int inventorySlotIndex) + { + var bagSlot = Globals.Bag[bagSlotIndex]; + if (bagSlot == default) { - var value = (int)Math.Round(((InputBox)sender).Value); - if (value > 0) - { - int[] userData = (int[])((InputBox)sender).UserData; - PacketSender.SendStoreBagItem(userData[0], value, userData[1]); - } + return; } - public void TryRetreiveBagItem(int bagSlotIndex, int inventorySlotIndex) + if (!ItemBase.TryGet(bagSlot.ItemId, out var itemDescriptor)) { - var bagSlot = Globals.Bag[bagSlotIndex]; - if (bagSlot == default) - { - return; - } + return; + } - if (!ItemBase.TryGet(bagSlot.ItemId, out var itemDescriptor)) - { - return; - } + var userData = new int[2] { bagSlotIndex, inventorySlotIndex }; - var userData = new int[2] { bagSlotIndex, inventorySlotIndex }; + var quantity = bagSlot.Quantity; + var maxQuantity = quantity; - var quantity = bagSlot.Quantity; - var maxQuantity = quantity; + // TODO: Refactor server bagging logic to allow transferring quantities from the entire inventory and not just the slot + //if (itemDescriptor.IsStackable) + //{ + // maxQuantity = GetQuantityOfItemInBag(itemDescriptor.Id); + //} - // TODO: Refactor server bagging logic to allow transferring quantities from the entire inventory and not just the slot - //if (itemDescriptor.IsStackable) - //{ - // maxQuantity = GetQuantityOfItemInBag(itemDescriptor.Id); - //} + if (maxQuantity < 2) + { + PacketSender.SendRetrieveBagItem(bagSlotIndex, 1, inventorySlotIndex); + return; + } - if (maxQuantity < 2) - { - PacketSender.SendRetrieveBagItem(bagSlotIndex, 1, inventorySlotIndex); - return; - } + InputBox.Open( + title: Strings.Bags.RetrieveItem, + prompt: Strings.Bags.RetrieveItemPrompt.ToString(itemDescriptor.Name), + modal: true, + inputType: InputBox.InputType.NumericSliderInput, + onSuccess: RetreiveBagItemInputBoxOkay, + onCancel: null, + userData: userData, + quantity: quantity, + maxQuantity: maxQuantity + ); + } - InputBox.Open( - title: Strings.Bags.RetrieveItem, - prompt: Strings.Bags.RetrieveItemPrompt.ToString(itemDescriptor.Name), - modal: true, - inputType: InputBox.InputType.NumericSliderInput, - onSuccess: RetreiveBagItemInputBoxOkay, - onCancel: null, - userData: userData, - quantity: quantity, - maxQuantity: maxQuantity - ); + private void RetreiveBagItemInputBoxOkay(object sender, EventArgs e) + { + var value = (int)Math.Round(((InputBox)sender).Value); + if (value > 0) + { + int[] userData = (int[])((InputBox)sender).UserData; + PacketSender.SendRetrieveBagItem(userData[0], value, userData[1]); } + } - private void RetreiveBagItemInputBoxOkay(object sender, EventArgs e) + //Trade + public void TryTradeItem(int index) + { + var slot = Inventory[index]; + var quantity = slot.Quantity; + var tradingItem = ItemBase.Get(slot.ItemId); + if (tradingItem == null) { - var value = (int)Math.Round(((InputBox)sender).Value); - if (value > 0) - { - int[] userData = (int[])((InputBox)sender).UserData; - PacketSender.SendRetrieveBagItem(userData[0], value, userData[1]); - } + return; } - //Trade - public void TryTradeItem(int index) + if (quantity == 1) { - var slot = Inventory[index]; - var quantity = slot.Quantity; - var tradingItem = ItemBase.Get(slot.ItemId); - if (tradingItem == null) - { - return; - } + PacketSender.SendOfferTradeItem(index, 1); + return; + } - if (quantity == 1) - { - PacketSender.SendOfferTradeItem(index, 1); - return; - } + InputBox.Open( + title: Strings.Trading.OfferItem, + prompt: Strings.Trading.OfferItemPrompt.ToString(tradingItem.Name), + modal: true, + inputType: InputBox.InputType.NumericSliderInput, + onSuccess: TradeItemInputBoxOkay, + onCancel: null, + userData: index, + quantity: quantity, + maxQuantity: quantity + ); + } - InputBox.Open( - title: Strings.Trading.OfferItem, - prompt: Strings.Trading.OfferItemPrompt.ToString(tradingItem.Name), - modal: true, - inputType: InputBox.InputType.NumericSliderInput, - onSuccess: TradeItemInputBoxOkay, - onCancel: null, - userData: index, - quantity: quantity, - maxQuantity: quantity - ); + private void TradeItemInputBoxOkay(object sender, EventArgs e) + { + var value = (int)Math.Round(((InputBox)sender).Value); + if (value > 0) + { + PacketSender.SendOfferTradeItem((int)((InputBox)sender).UserData, value); } + } - private void TradeItemInputBoxOkay(object sender, EventArgs e) + public void TryRevokeItem(int index) + { + var slot = Globals.Trade[0, index]; + var quantity = slot.Quantity; + var revokedItem = ItemBase.Get(slot.ItemId); + if (revokedItem == null) { - var value = (int)Math.Round(((InputBox)sender).Value); - if (value > 0) - { - PacketSender.SendOfferTradeItem((int)((InputBox)sender).UserData, value); - } + return; } - public void TryRevokeItem(int index) + if (quantity == 1) { - var slot = Globals.Trade[0, index]; - var quantity = slot.Quantity; - var revokedItem = ItemBase.Get(slot.ItemId); - if (revokedItem == null) - { - return; - } + PacketSender.SendRevokeTradeItem(index, 1); + return; + } - if (quantity == 1) - { - PacketSender.SendRevokeTradeItem(index, 1); - return; - } + InputBox.Open( + title: Strings.Trading.RevokeItem, + prompt: Strings.Trading.RevokeItemPrompt.ToString(revokedItem.Name), + modal: true, + inputType: InputBox.InputType.NumericSliderInput, + onSuccess: RevokeItemInputBoxOkay, + onCancel: null, + userData: index, + quantity: quantity, + maxQuantity: quantity + ); + } + + private void RevokeItemInputBoxOkay(object sender, EventArgs e) + { + var value = (int)Math.Round(((InputBox)sender).Value); + if (value > 0) + { + PacketSender.SendRevokeTradeItem((int)((InputBox)sender).UserData, value); + } + } + + //Spell Processing + public void SwapSpells(int fromSpellIndex, int toSpellIndex) + { + PacketSender.SendSwapSpells(fromSpellIndex, toSpellIndex); + var tmpInstance = Spells[toSpellIndex]; + Spells[toSpellIndex] = Spells[fromSpellIndex]; + Spells[fromSpellIndex] = tmpInstance; + } + public void TryForgetSpell(int spellIndex) + { + var spellSlot = Spells[spellIndex]; + if (SpellBase.TryGet(spellSlot.Id, out var spellDescriptor)) + { InputBox.Open( - title: Strings.Trading.RevokeItem, - prompt: Strings.Trading.RevokeItemPrompt.ToString(revokedItem.Name), + title: Strings.Spells.ForgetSpell, + prompt: Strings.Spells.ForgetSpellPrompt.ToString(spellDescriptor.Name), modal: true, - inputType: InputBox.InputType.NumericSliderInput, - onSuccess: RevokeItemInputBoxOkay, + inputType: InputBox.InputType.YesNo, + onSuccess: ForgetSpellInputBoxOkay, onCancel: null, - userData: index, - quantity: quantity, - maxQuantity: quantity + userData: spellIndex ); } + } - private void RevokeItemInputBoxOkay(object sender, EventArgs e) + private void ForgetSpellInputBoxOkay(object sender, EventArgs e) + { + PacketSender.SendForgetSpell((int)((InputBox)sender).UserData); + } + + public void TryUseSpell(int index) + { + if (Spells[index].Id != Guid.Empty && + (GetSpellRemainingCooldown(index) < Timing.Global.Milliseconds)) { - var value = (int)Math.Round(((InputBox)sender).Value); - if (value > 0) + var spellBase = SpellBase.Get(Spells[index].Id); + + if (spellBase.CastDuration > 0 && (Options.Instance.CombatOpts.MovementCancelsCast && Globals.Me.IsMoving)) { - PacketSender.SendRevokeTradeItem((int)((InputBox)sender).UserData, value); + return; } + + PacketSender.SendUseSpell(index, TargetIndex); } + } - //Spell Processing - public void SwapSpells(int fromSpellIndex, int toSpellIndex) + public long GetSpellCooldown(Guid id) + { + if (SpellCooldowns.TryGetValue(id, out var cd) && cd > Timing.Global.Milliseconds) { - PacketSender.SendSwapSpells(fromSpellIndex, toSpellIndex); - var tmpInstance = Spells[toSpellIndex]; - Spells[toSpellIndex] = Spells[fromSpellIndex]; - Spells[fromSpellIndex] = tmpInstance; + return cd; } - public void TryForgetSpell(int spellIndex) + if ((SpellBase.TryGet(id, out var spellBase) && !spellBase.IgnoreGlobalCooldown) && Globals.Me.GlobalCooldown > Timing.Global.Milliseconds) { - var spellSlot = Spells[spellIndex]; - if (SpellBase.TryGet(spellSlot.Id, out var spellDescriptor)) - { - InputBox.Open( - title: Strings.Spells.ForgetSpell, - prompt: Strings.Spells.ForgetSpellPrompt.ToString(spellDescriptor.Name), - modal: true, - inputType: InputBox.InputType.YesNo, - onSuccess: ForgetSpellInputBoxOkay, - onCancel: null, - userData: spellIndex - ); - } + return Globals.Me.GlobalCooldown; } - private void ForgetSpellInputBoxOkay(object sender, EventArgs e) + return 0; + } + + public void TryUseSpell(Guid spellId) + { + if (spellId == Guid.Empty) { - PacketSender.SendForgetSpell((int)((InputBox)sender).UserData); + return; } - public void TryUseSpell(int index) + for (var i = 0; i < Spells.Length; i++) { - if (Spells[index].Id != Guid.Empty && - (GetSpellRemainingCooldown(index) < Timing.Global.Milliseconds)) + if (Spells[i].Id == spellId) { - var spellBase = SpellBase.Get(Spells[index].Id); - - if (spellBase.CastDuration > 0 && (Options.Instance.CombatOpts.MovementCancelsCast && Globals.Me.IsMoving)) - { - return; - } + TryUseSpell(i); - PacketSender.SendUseSpell(index, TargetIndex); + return; } } + } - public long GetSpellCooldown(Guid id) + public int FindHotbarSpell(IHotbarInstance hotbarInstance) + { + if (hotbarInstance.ItemOrSpellId != Guid.Empty && SpellBase.Get(hotbarInstance.ItemOrSpellId) != null) { - if (SpellCooldowns.TryGetValue(id, out var cd) && cd > Timing.Global.Milliseconds) + for (var i = 0; i < Spells.Length; i++) { - return cd; + if (Spells[i].Id == hotbarInstance.ItemOrSpellId) + { + return i; + } } + } + + return -1; + } - if ((SpellBase.TryGet(id, out var spellBase) && !spellBase.IgnoreGlobalCooldown) && Globals.Me.GlobalCooldown > Timing.Global.Milliseconds) + //Hotbar Processing + public void AddToHotbar(int hotbarSlot, sbyte itemType, int itemSlot) + { + Hotbar[hotbarSlot].ItemOrSpellId = Guid.Empty; + Hotbar[hotbarSlot].PreferredStatBuffs = new int[Enum.GetValues().Length]; + if (itemType == 0) + { + var item = Inventory[itemSlot]; + if (item != null) { - return Globals.Me.GlobalCooldown; + Hotbar[hotbarSlot].ItemOrSpellId = item.ItemId; + Hotbar[hotbarSlot].PreferredStatBuffs = item.ItemProperties.StatModifiers; } - - return 0; } - - public void TryUseSpell(Guid spellId) + else if (itemType == 1) { - if (spellId == Guid.Empty) + var spell = Spells[itemSlot]; + if (spell != null) { - return; + Hotbar[hotbarSlot].ItemOrSpellId = spell.Id; } + } - for (var i = 0; i < Spells.Length; i++) - { - if (Spells[i].Id == spellId) - { - TryUseSpell(i); + PacketSender.SendHotbarUpdate(hotbarSlot, itemType, itemSlot); + } - return; - } - } - } + public void HotbarSwap(int index, int swapIndex) + { + var itemId = Hotbar[index].ItemOrSpellId; + var bagId = Hotbar[index].BagId; + var stats = Hotbar[index].PreferredStatBuffs; + + Hotbar[index].ItemOrSpellId = Hotbar[swapIndex].ItemOrSpellId; + Hotbar[index].BagId = Hotbar[swapIndex].BagId; + Hotbar[index].PreferredStatBuffs = Hotbar[swapIndex].PreferredStatBuffs; + + Hotbar[swapIndex].ItemOrSpellId = itemId; + Hotbar[swapIndex].BagId = bagId; + Hotbar[swapIndex].PreferredStatBuffs = stats; + + PacketSender.SendHotbarSwap(index, swapIndex); + } - public int FindHotbarSpell(IHotbarInstance hotbarInstance) + // Change the dimension if the player is on a gateway + private void TryToChangeDimension() + { + if (X < Options.MapWidth && X >= 0) { - if (hotbarInstance.ItemOrSpellId != Guid.Empty && SpellBase.Get(hotbarInstance.ItemOrSpellId) != null) + if (Y < Options.MapHeight && Y >= 0) { - for (var i = 0; i < Spells.Length; i++) + if (Maps.MapInstance.Get(MapId) != null && Maps.MapInstance.Get(MapId).Attributes[X, Y] != null) { - if (Spells[i].Id == hotbarInstance.ItemOrSpellId) + if (Maps.MapInstance.Get(MapId).Attributes[X, Y].Type == MapAttribute.ZDimension) { - return i; + if (((MapZDimensionAttribute)Maps.MapInstance.Get(MapId).Attributes[X, Y]).GatewayTo > 0) + { + Z = (byte)(((MapZDimensionAttribute)Maps.MapInstance.Get(MapId).Attributes[X, Y]) + .GatewayTo - + 1); + } } } } - - return -1; } + } - //Hotbar Processing - public void AddToHotbar(int hotbarSlot, sbyte itemType, int itemSlot) - { - Hotbar[hotbarSlot].ItemOrSpellId = Guid.Empty; - Hotbar[hotbarSlot].PreferredStatBuffs = new int[Enum.GetValues().Length]; - if (itemType == 0) - { - var item = Inventory[itemSlot]; - if (item != null) - { - Hotbar[hotbarSlot].ItemOrSpellId = item.ItemId; - Hotbar[hotbarSlot].PreferredStatBuffs = item.ItemProperties.StatModifiers; - } - } - else if (itemType == 1) - { - var spell = Spells[itemSlot]; - if (spell != null) - { - Hotbar[hotbarSlot].ItemOrSpellId = spell.Id; - } - } + //Input Handling + private void HandleInput() + { + var inputX = 0; + var inputY = 0; - PacketSender.SendHotbarUpdate(hotbarSlot, itemType, itemSlot); + if (Interface.Interface.HasInputFocus()) + { + return; } - public void HotbarSwap(int index, int swapIndex) + if (Controls.KeyDown(Control.MoveUp)) { - var itemId = Hotbar[index].ItemOrSpellId; - var bagId = Hotbar[index].BagId; - var stats = Hotbar[index].PreferredStatBuffs; - - Hotbar[index].ItemOrSpellId = Hotbar[swapIndex].ItemOrSpellId; - Hotbar[index].BagId = Hotbar[swapIndex].BagId; - Hotbar[index].PreferredStatBuffs = Hotbar[swapIndex].PreferredStatBuffs; - - Hotbar[swapIndex].ItemOrSpellId = itemId; - Hotbar[swapIndex].BagId = bagId; - Hotbar[swapIndex].PreferredStatBuffs = stats; - - PacketSender.SendHotbarSwap(index, swapIndex); + inputY += 1; } - // Change the dimension if the player is on a gateway - private void TryToChangeDimension() + if (Controls.KeyDown(Control.MoveDown)) { - if (X < Options.MapWidth && X >= 0) - { - if (Y < Options.MapHeight && Y >= 0) - { - if (Maps.MapInstance.Get(MapId) != null && Maps.MapInstance.Get(MapId).Attributes[X, Y] != null) - { - if (Maps.MapInstance.Get(MapId).Attributes[X, Y].Type == MapAttribute.ZDimension) - { - if (((MapZDimensionAttribute)Maps.MapInstance.Get(MapId).Attributes[X, Y]).GatewayTo > 0) - { - Z = (byte)(((MapZDimensionAttribute)Maps.MapInstance.Get(MapId).Attributes[X, Y]) - .GatewayTo - - 1); - } - } - } - } - } + inputY -= 1; } - //Input Handling - private void HandleInput() + if (Controls.KeyDown(Control.MoveLeft)) { - var inputX = 0; - var inputY = 0; - - if (Interface.Interface.HasInputFocus()) - { - return; - } + inputX -= 1; + } - if (Controls.KeyDown(Control.MoveUp)) - { - inputY += 1; - } + if (Controls.KeyDown(Control.MoveRight)) + { + inputX += 1; + } - if (Controls.KeyDown(Control.MoveDown)) + Direction inputDirection; + if (inputX == 0 && inputY == 0) + { + inputDirection = Direction.None; + } + else + { + var diagonalMovement = inputX != 0 && Options.Instance.MapOpts.EnableDiagonalMovement; + var inputXDirection = Math.Sign(inputX) switch { - inputY -= 1; - } - - if (Controls.KeyDown(Control.MoveLeft)) + < 0 => Direction.Left, + > 0 => Direction.Right, + _ => Direction.None, + }; + var inputYDirection = Math.Sign(inputY) switch { - inputX -= 1; - } + < 0 => Direction.Down, + > 0 => Direction.Up, + _ => Direction.None, + }; - if (Controls.KeyDown(Control.MoveRight)) + if (diagonalMovement) { - inputX += 1; + inputDirection = inputYDirection switch + { + Direction.Down => inputXDirection switch + { + Direction.Left => Direction.DownLeft, + Direction.Right => Direction.DownRight, + _ => inputYDirection, + }, + Direction.Up => inputXDirection switch + { + Direction.Left => Direction.UpLeft, + Direction.Right => Direction.UpRight, + _ => inputYDirection, + }, + _ => inputXDirection, + }; } - - Direction inputDirection; - if (inputX == 0 && inputY == 0) + else if (inputYDirection != Direction.None) { - inputDirection = Direction.None; + inputDirection = inputYDirection; } else { - var diagonalMovement = inputX != 0 && Options.Instance.MapOpts.EnableDiagonalMovement; - var inputXDirection = Math.Sign(inputX) switch - { - < 0 => Direction.Left, - > 0 => Direction.Right, - _ => Direction.None, - }; - var inputYDirection = Math.Sign(inputY) switch - { - < 0 => Direction.Down, - > 0 => Direction.Up, - _ => Direction.None, - }; - - if (diagonalMovement) - { - inputDirection = inputYDirection switch - { - Direction.Down => inputXDirection switch - { - Direction.Left => Direction.DownLeft, - Direction.Right => Direction.DownRight, - _ => inputYDirection, - }, - Direction.Up => inputXDirection switch - { - Direction.Left => Direction.UpLeft, - Direction.Right => Direction.UpRight, - _ => inputYDirection, - }, - _ => inputXDirection, - }; - } - else if (inputYDirection != Direction.None) - { - inputDirection = inputYDirection; - } - else - { - inputDirection = inputXDirection; - } + inputDirection = inputXDirection; } + } - Globals.Me.MoveDir = inputDirection; + Globals.Me.MoveDir = inputDirection; - TurnAround(); + TurnAround(); - var castInput = -1; - for (var barSlot = 0; barSlot < Options.Instance.PlayerOpts.HotbarSlotCount; barSlot++) + var castInput = -1; + for (var barSlot = 0; barSlot < Options.Instance.PlayerOpts.HotbarSlotCount; barSlot++) + { + if (!mLastHotbarUseTime.ContainsKey(barSlot)) { - if (!mLastHotbarUseTime.ContainsKey(barSlot)) - { - mLastHotbarUseTime.Add(barSlot, 0); - } - - if (Controls.KeyDown((Control)barSlot + (int)Control.Hotkey1)) - { - castInput = barSlot; - } + mLastHotbarUseTime.Add(barSlot, 0); } - if (castInput != -1) + if (Controls.KeyDown((Control)barSlot + (int)Control.Hotkey1)) { - if (0 <= castInput && castInput < Interface.Interface.GameUi?.Hotbar?.Items?.Count && mLastHotbarUseTime[castInput] < Timing.Global.Milliseconds) - { - Interface.Interface.GameUi?.Hotbar?.Items?[castInput]?.Activate(); - mLastHotbarUseTime[castInput] = Timing.Global.Milliseconds + mHotbarUseDelay; - } + castInput = barSlot; } } - protected int GetDistanceTo(IEntity target) + if (castInput != -1) { - if (target != null) + if (0 <= castInput && castInput < Interface.Interface.GameUi?.Hotbar?.Items?.Count && mLastHotbarUseTime[castInput] < Timing.Global.Milliseconds) { - var myMap = Maps.MapInstance.Get(MapId); - var targetMap = Maps.MapInstance.Get(target.MapId); - if (myMap != null && targetMap != null) - { - //Calculate World Tile of Me - var x1 = X + myMap.GridX * Options.MapWidth; - var y1 = Y + myMap.GridY * Options.MapHeight; - - //Calculate world tile of target - var x2 = target.X + targetMap.GridX * Options.MapWidth; - var y2 = target.Y + targetMap.GridY * Options.MapHeight; - - return (int)Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2)); - } + Interface.Interface.GameUi?.Hotbar?.Items?[castInput]?.Activate(); + mLastHotbarUseTime[castInput] = Timing.Global.Milliseconds + mHotbarUseDelay; } - - //Something is null.. return a value that is out of range :) - return 9999; } + } - public void AutoTarget() + protected int GetDistanceTo(IEntity target) + { + if (target != null) { - //Check for taunt status if so don't allow to change target - for (var i = 0; i < Status.Count; i++) + var myMap = Maps.MapInstance.Get(MapId); + var targetMap = Maps.MapInstance.Get(target.MapId); + if (myMap != null && targetMap != null) { - if (Status[i].Type == SpellEffect.Taunt) - { - return; - } + //Calculate World Tile of Me + var x1 = X + myMap.GridX * Options.MapWidth; + var y1 = Y + myMap.GridY * Options.MapHeight; + + //Calculate world tile of target + var x2 = target.X + targetMap.GridX * Options.MapWidth; + var y2 = target.Y + targetMap.GridY * Options.MapHeight; + + return (int)Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2)); } + } - // Do we need to account for players? - // Depends on what type of map we're currently on. - if (Globals.Me.MapInstance == null) + //Something is null.. return a value that is out of range :) + return 9999; + } + + public void AutoTarget() + { + //Check for taunt status if so don't allow to change target + for (var i = 0; i < Status.Count; i++) + { + if (Status[i].Type == SpellEffect.Taunt) { return; } - var currentMap = Globals.Me.MapInstance as MapInstance; - var canTargetPlayers = currentMap.ZoneType != MapZone.Safe; + } + + // Do we need to account for players? + // Depends on what type of map we're currently on. + if (Globals.Me.MapInstance == null) + { + return; + } + var currentMap = Globals.Me.MapInstance as MapInstance; + var canTargetPlayers = currentMap.ZoneType != MapZone.Safe; - // Build a list of Entities to select from with positions if our list is either old, we've moved or changed maps somehow. - if ( - mlastTargetScanTime < Timing.Global.Milliseconds || - mlastTargetScanMap != Globals.Me.MapId || - mlastTargetScanLocation != new Point(X, Y) - ) + // Build a list of Entities to select from with positions if our list is either old, we've moved or changed maps somehow. + if ( + mlastTargetScanTime < Timing.Global.Milliseconds || + mlastTargetScanMap != Globals.Me.MapId || + mlastTargetScanLocation != new Point(X, Y) + ) + { + // Add new items to our list! + foreach (var en in Globals.Entities) { - // Add new items to our list! - foreach (var en in Globals.Entities) + // Check if this is a valid entity. + if (en.Value == null) { - // Check if this is a valid entity. - if (en.Value == null) - { - continue; - } - - // Don't allow us to auto target ourselves. - if (en.Value == Globals.Me) - { - continue; - } - - // Check if the entity has stealth status - if (en.Value.IsHidden || (en.Value.IsStealthed && !Globals.Me.IsInMyParty(en.Value.Id))) - { - continue; - } - - // Check if we are allowed to target players here, if we're not and this is a player then skip! - // If we are, check to see if they're our party or nation member, then exclude them. We're friendly happy people here. - if (!canTargetPlayers && en.Value.Type == EntityType.Player) - { - continue; - } - - if (canTargetPlayers && en.Value.Type == EntityType.Player) - { - var player = en.Value as Player; - if (IsInMyParty(player)) - { - continue; - } - } - - if (en.Value.Type == EntityType.GlobalEntity || en.Value.Type == EntityType.Player) - { - // Already in our list? - if (mlastTargetList.ContainsKey(en.Value)) - { - mlastTargetList[en.Value].DistanceTo = GetDistanceTo(en.Value); - } - else - { - // Add entity with blank time. Never been selected. - mlastTargetList.Add(en.Value, new TargetInfo { DistanceTo = GetDistanceTo(en.Value), LastTimeSelected = 0 }); - } - } + continue; } - // Remove old items. - var toRemove = mlastTargetList.Where(en => !Globals.Entities.ContainsValue(en.Key)).ToArray(); - foreach (var en in toRemove) + // Don't allow us to auto target ourselves. + if (en.Value == Globals.Me) { - mlastTargetList.Remove(en.Key); + continue; } - // Skip scanning for another second or so.. And set up other values. - mlastTargetScanTime = Timing.Global.Milliseconds + 300; - mlastTargetScanMap = MapId; - mlastTargetScanLocation = new Point(X, Y); - } - - // Find valid entities. - var validEntities = mlastTargetList.ToArray(); - - // Reduce the number of targets down to what is in our allowed range. - validEntities = validEntities.Where(en => en.Value.DistanceTo <= Options.Combat.MaxPlayerAutoTargetRadius).ToArray(); + // Check if the entity has stealth status + if (en.Value.IsHidden || (en.Value.IsStealthed && !Globals.Me.IsInMyParty(en.Value.Id))) + { + continue; + } - int currentDistance = 9999; - long currentTime = Timing.Global.Milliseconds; - Entity currentEntity = mLastEntitySelected; - foreach (var entity in validEntities) - { - if (currentEntity == entity.Key) + // Check if we are allowed to target players here, if we're not and this is a player then skip! + // If we are, check to see if they're our party or nation member, then exclude them. We're friendly happy people here. + if (!canTargetPlayers && en.Value.Type == EntityType.Player) { continue; } - // if distance is the same - if (entity.Value.DistanceTo == currentDistance) + if (canTargetPlayers && en.Value.Type == EntityType.Player) { - if (entity.Value.LastTimeSelected < currentTime) + var player = en.Value as Player; + if (IsInMyParty(player)) { - currentTime = entity.Value.LastTimeSelected; - currentDistance = entity.Value.DistanceTo; - currentEntity = entity.Key; + continue; } } - else if (entity.Value.DistanceTo < currentDistance) + + if (en.Value.Type == EntityType.GlobalEntity || en.Value.Type == EntityType.Player) { - if (entity.Value.LastTimeSelected < currentTime || entity.Value.LastTimeSelected == currentTime) + // Already in our list? + if (mlastTargetList.ContainsKey(en.Value)) { - currentTime = entity.Value.LastTimeSelected; - currentDistance = entity.Value.DistanceTo; - currentEntity = entity.Key; + mlastTargetList[en.Value].DistanceTo = GetDistanceTo(en.Value); + } + else + { + // Add entity with blank time. Never been selected. + mlastTargetList.Add(en.Value, new TargetInfo { DistanceTo = GetDistanceTo(en.Value), LastTimeSelected = 0 }); } } } - // We didn't target anything? Can we default to closest? - if (currentEntity == null) + // Remove old items. + var toRemove = mlastTargetList.Where(en => !Globals.Entities.ContainsValue(en.Key)).ToArray(); + foreach (var en in toRemove) { - currentEntity = validEntities.Where(x => x.Value.DistanceTo == validEntities.Min(y => y.Value.DistanceTo)).FirstOrDefault().Key; - - // Also reset our target times so we can start auto targetting again. - foreach (var entity in mlastTargetList) - { - entity.Value.LastTimeSelected = 0; - } + mlastTargetList.Remove(en.Key); } - if (currentEntity == null) - { - mLastEntitySelected = null; - return; - } + // Skip scanning for another second or so.. And set up other values. + mlastTargetScanTime = Timing.Global.Milliseconds + 300; + mlastTargetScanMap = MapId; + mlastTargetScanLocation = new Point(X, Y); + } - if(!Globals.Entities.TryGetValue(currentEntity.Id, out var targetedEntity)) + // Find valid entities. + var validEntities = mlastTargetList.ToArray(); + + // Reduce the number of targets down to what is in our allowed range. + validEntities = validEntities.Where(en => en.Value.DistanceTo <= Options.Combat.MaxPlayerAutoTargetRadius).ToArray(); + + int currentDistance = 9999; + long currentTime = Timing.Global.Milliseconds; + Entity currentEntity = mLastEntitySelected; + foreach (var entity in validEntities) + { + if (currentEntity == entity.Key) { - return; + continue; } - if (mlastTargetList.TryGetValue(targetedEntity, out var lastTarget)) + // if distance is the same + if (entity.Value.DistanceTo == currentDistance) { - lastTarget.LastTimeSelected = Timing.Global.Milliseconds; + if (entity.Value.LastTimeSelected < currentTime) + { + currentTime = entity.Value.LastTimeSelected; + currentDistance = entity.Value.DistanceTo; + currentEntity = entity.Key; + } } - mLastEntitySelected = targetedEntity; - - if (TargetIndex != targetedEntity.Id) + else if (entity.Value.DistanceTo < currentDistance) { - SetTargetBox(targetedEntity); - TargetIndex = targetedEntity.Id; - TargetType = 0; + if (entity.Value.LastTimeSelected < currentTime || entity.Value.LastTimeSelected == currentTime) + { + currentTime = entity.Value.LastTimeSelected; + currentDistance = entity.Value.DistanceTo; + currentEntity = entity.Key; + } } } - private void SetTargetBox(Entity en) + // We didn't target anything? Can we default to closest? + if (currentEntity == null) { - if (en == null) - { - TargetBox?.SetEntity(null); - TargetBox?.Hide(); - PacketSender.SendTarget(Guid.Empty); - return; - } + currentEntity = validEntities.Where(x => x.Value.DistanceTo == validEntities.Min(y => y.Value.DistanceTo)).FirstOrDefault().Key; - if (en is Player) - { - TargetBox?.SetEntity(en, EntityType.Player); - } - else if (en is Event) - { - TargetBox?.SetEntity(en, EntityType.Event); - } - else + // Also reset our target times so we can start auto targetting again. + foreach (var entity in mlastTargetList) { - TargetBox?.SetEntity(en, EntityType.GlobalEntity); + entity.Value.LastTimeSelected = 0; } + } - TargetBox?.Show(); - PacketSender.SendTarget(en.Id); + if (currentEntity == null) + { + mLastEntitySelected = null; + return; } - private void AutoTurnToTarget(Entity en) + if(!Globals.Entities.TryGetValue(currentEntity.Id, out var targetedEntity)) { - if (en == this) - { - return; - } + return; + } - if (!Globals.Database.AutoTurnToTarget) - { - return; - } + if (mlastTargetList.TryGetValue(targetedEntity, out var lastTarget)) + { + lastTarget.LastTimeSelected = Timing.Global.Milliseconds; + } + mLastEntitySelected = targetedEntity; - if (!Options.Instance.PlayerOpts.EnableAutoTurnToTarget) - { - return; - } + if (TargetIndex != targetedEntity.Id) + { + SetTargetBox(targetedEntity); + TargetIndex = targetedEntity.Id; + TargetType = 0; + } + } - if (Controls.KeyDown(Control.TurnAround)) - { - return; - } + private void SetTargetBox(Entity en) + { + if (en == null) + { + TargetBox?.SetEntity(null); + TargetBox?.Hide(); + PacketSender.SendTarget(Guid.Empty); + return; + } - if (IsTurnAroundWhileCastingDisabled) - { - return; - } + if (en is Player) + { + TargetBox?.SetEntity(en, EntityType.Player); + } + else if (en is Event) + { + TargetBox?.SetEntity(en, EntityType.Event); + } + else + { + TargetBox?.SetEntity(en, EntityType.GlobalEntity); + } - var directionToTarget = DirectionToTarget(en); + TargetBox?.Show(); + PacketSender.SendTarget(en.Id); + } - if (IsMoving || Dir == MoveDir || Dir == directionToTarget) - { - AutoTurnToTargetTimer = Timing.Global.Milliseconds + Options.Instance.PlayerOpts.AutoTurnToTargetDelay; - return; - } + private void AutoTurnToTarget(Entity en) + { + if (en == this) + { + return; + } - if (AutoTurnToTargetTimer > Timing.Global.Milliseconds) - { - return; - } + if (!Globals.Database.AutoTurnToTarget) + { + return; + } - if (Options.Instance.PlayerOpts.AutoTurnToTargetIgnoresEntitiesBehind && - IsTargetAtOppositeDirection(Dir, directionToTarget)) - { - return; - } + if (!Options.Instance.PlayerOpts.EnableAutoTurnToTarget) + { + return; + } - MoveDir = Direction.None; - Dir = directionToTarget; - PacketSender.SendDirection(Dir); - PickLastDirection(Dir); + if (Controls.KeyDown(Control.TurnAround)) + { + return; } - public bool TryBlock() + if (IsTurnAroundWhileCastingDisabled) { - var shieldIndex = Options.ShieldIndex; - var myShieldIndex = MyEquipment[shieldIndex]; + return; + } - // Return false if character is attacking, or blocking or if they don't have a shield equipped. - if (IsAttacking || IsBlocking || shieldIndex < 0 || myShieldIndex < 0) - { - return false; - } + var directionToTarget = DirectionToTarget(en); - // Return false if the shield item descriptor could not be retrieved. - if (!ItemBase.TryGet(Inventory[myShieldIndex].ItemId, out _)) - { - return false; - } + if (IsMoving || Dir == MoveDir || Dir == directionToTarget) + { + AutoTurnToTargetTimer = Timing.Global.Milliseconds + Options.Instance.PlayerOpts.AutoTurnToTargetDelay; + return; + } - IsBlocking = true; - PacketSender.SendBlock(IsBlocking); - return IsBlocking; + if (AutoTurnToTargetTimer > Timing.Global.Milliseconds) + { + return; } - public bool TryAttack() + if (Options.Instance.PlayerOpts.AutoTurnToTargetIgnoresEntitiesBehind && + IsTargetAtOppositeDirection(Dir, directionToTarget)) { - if (IsAttacking || IsBlocking || (IsMoving && !Options.Instance.PlayerOpts.AllowCombatMovement)) - { - return false; - } + return; + } - int x = Globals.Me.X; - int y = Globals.Me.Y; - var map = Globals.Me.MapId; + MoveDir = Direction.None; + Dir = directionToTarget; + PacketSender.SendDirection(Dir); + PickLastDirection(Dir); + } - switch (Globals.Me.Dir) - { - case Direction.Up: - y--; - break; + public bool TryBlock() + { + var shieldIndex = Options.ShieldIndex; + var myShieldIndex = MyEquipment[shieldIndex]; - case Direction.Down: - y++; - break; + // Return false if character is attacking, or blocking or if they don't have a shield equipped. + if (IsAttacking || IsBlocking || shieldIndex < 0 || myShieldIndex < 0) + { + return false; + } - case Direction.Left: - x--; - break; + // Return false if the shield item descriptor could not be retrieved. + if (!ItemBase.TryGet(Inventory[myShieldIndex].ItemId, out _)) + { + return false; + } - case Direction.Right: - x++; - break; + IsBlocking = true; + PacketSender.SendBlock(IsBlocking); + return IsBlocking; + } - case Direction.UpLeft: - y--; - x--; - break; + public bool TryAttack() + { + if (IsAttacking || IsBlocking || (IsMoving && !Options.Instance.PlayerOpts.AllowCombatMovement)) + { + return false; + } - case Direction.UpRight: - y--; - x++; - break; + int x = Globals.Me.X; + int y = Globals.Me.Y; + var map = Globals.Me.MapId; - case Direction.DownRight: - y++; - x++; - break; + switch (Globals.Me.Dir) + { + case Direction.Up: + y--; + break; - case Direction.DownLeft: - y++; - x--; - break; - } + case Direction.Down: + y++; + break; + + case Direction.Left: + x--; + break; + + case Direction.Right: + x++; + break; + + case Direction.UpLeft: + y--; + x--; + break; + + case Direction.UpRight: + y--; + x++; + break; - if (TryGetRealLocation(ref x, ref y, ref map)) + case Direction.DownRight: + y++; + x++; + break; + + case Direction.DownLeft: + y++; + x--; + break; + } + + if (TryGetRealLocation(ref x, ref y, ref map)) + { + // Iterate through all entities + foreach (var en in Globals.Entities) { - // Iterate through all entities - foreach (var en in Globals.Entities) + // Skip if the entity is null or is not within the player's map. + if (en.Value?.MapId != map) { - // Skip if the entity is null or is not within the player's map. - if (en.Value?.MapId != map) - { - continue; - } + continue; + } - // Skip if the entity is the current player. - if (en.Value == Globals.Me) - { - continue; - } + // Skip if the entity is the current player. + if (en.Value == Globals.Me) + { + continue; + } - // Skip if the entity can't be attacked. - if (!en.Value.CanBeAttacked) - { - continue; - } + // Skip if the entity can't be attacked. + if (!en.Value.CanBeAttacked) + { + continue; + } - if (en.Value.X != x || en.Value.Y != y) - { - continue; - } + if (en.Value.X != x || en.Value.Y != y) + { + continue; + } - // Attack the entity. - PacketSender.SendAttack(en.Key); - AttackTimer = Timing.Global.Milliseconds + CalculateAttackTime(); + // Attack the entity. + PacketSender.SendAttack(en.Key); + AttackTimer = Timing.Global.Milliseconds + CalculateAttackTime(); - return true; - } + return true; } + } - foreach (MapInstance eventMap in Maps.MapInstance.Lookup.Values) + foreach (MapInstance eventMap in Maps.MapInstance.Lookup.Values) + { + foreach (var en in eventMap.LocalEntities) { - foreach (var en in eventMap.LocalEntities) + if (en.Value == null) { - if (en.Value == null) - { - continue; - } + continue; + } - if (en.Value.MapId == map && en.Value.X == x && en.Value.Y == y) + if (en.Value.MapId == map && en.Value.X == x && en.Value.Y == y) + { + if (en.Value is Event evt && evt.Trigger == EventTrigger.ActionButton) { - if (en.Value is Event evt && evt.Trigger == EventTrigger.ActionButton) - { - //Talk to Event - PacketSender.SendActivateEvent(en.Key); - AttackTimer = Timing.Global.Milliseconds + CalculateAttackTime(); + //Talk to Event + PacketSender.SendActivateEvent(en.Key); + AttackTimer = Timing.Global.Milliseconds + CalculateAttackTime(); - return true; - } + return true; } } } + } - //Projectile/empty swing for animations - PacketSender.SendAttack(Guid.Empty); - AttackTimer = Timing.Global.Milliseconds + CalculateAttackTime(); + //Projectile/empty swing for animations + PacketSender.SendAttack(Guid.Empty); + AttackTimer = Timing.Global.Milliseconds + CalculateAttackTime(); - return true; - } + return true; + } - public bool TryGetRealLocation(ref int x, ref int y, ref Guid mapId) + public bool TryGetRealLocation(ref int x, ref int y, ref Guid mapId) + { + var tmpX = x; + var tmpY = y; + var tmpI = -1; + if (Maps.MapInstance.Get(mapId) != null) { - var tmpX = x; - var tmpY = y; - var tmpI = -1; - if (Maps.MapInstance.Get(mapId) != null) - { - var gridX = Maps.MapInstance.Get(mapId).GridX; - var gridY = Maps.MapInstance.Get(mapId).GridY; + var gridX = Maps.MapInstance.Get(mapId).GridX; + var gridY = Maps.MapInstance.Get(mapId).GridY; - if (x < 0) - { - tmpX = Options.MapWidth - x * -1; - gridX--; - } + if (x < 0) + { + tmpX = Options.MapWidth - x * -1; + gridX--; + } - if (y < 0) - { - tmpY = Options.MapHeight - y * -1; - gridY--; - } + if (y < 0) + { + tmpY = Options.MapHeight - y * -1; + gridY--; + } - if (y > Options.MapHeight - 1) - { - tmpY = y - Options.MapHeight; - gridY++; - } + if (y > Options.MapHeight - 1) + { + tmpY = y - Options.MapHeight; + gridY++; + } - if (x > Options.MapWidth - 1) - { - tmpX = x - Options.MapWidth; - gridX++; - } + if (x > Options.MapWidth - 1) + { + tmpX = x - Options.MapWidth; + gridX++; + } - if (gridX >= 0 && gridX < Globals.MapGridWidth && gridY >= 0 && gridY < Globals.MapGridHeight) + if (gridX >= 0 && gridX < Globals.MapGridWidth && gridY >= 0 && gridY < Globals.MapGridHeight) + { + if (Maps.MapInstance.Get(Globals.MapGrid[gridX, gridY]) != null) { - if (Maps.MapInstance.Get(Globals.MapGrid[gridX, gridY]) != null) - { - x = (byte)tmpX; - y = (byte)tmpY; - mapId = Globals.MapGrid[gridX, gridY]; + x = (byte)tmpX; + y = (byte)tmpY; + mapId = Globals.MapGrid[gridX, gridY]; - return true; - } + return true; } } - - return false; } - public bool TryTarget() + return false; + } + + public bool TryTarget() + { + //Check for taunt status if so don't allow to change target + for (var i = 0; i < Status.Count; i++) { - //Check for taunt status if so don't allow to change target - for (var i = 0; i < Status.Count; i++) + if (Status[i].Type == SpellEffect.Taunt) { - if (Status[i].Type == SpellEffect.Taunt) - { - return false; - } + return false; } + } - var mouseInWorld = Graphics.ConvertToWorldPoint(Globals.InputManager.GetMousePosition()); - var x = (int)mouseInWorld.X; - var y = (int)mouseInWorld.Y; - var targetRect = new FloatRect(x - 8, y - 8, 16, 16); //Adjust to allow more/less error + var mouseInWorld = Graphics.ConvertToWorldPoint(Globals.InputManager.GetMousePosition()); + var x = (int)mouseInWorld.X; + var y = (int)mouseInWorld.Y; + var targetRect = new FloatRect(x - 8, y - 8, 16, 16); //Adjust to allow more/less error - IEntity bestMatch = null; - var bestAreaMatch = 0f; + IEntity bestMatch = null; + var bestAreaMatch = 0f; - foreach (MapInstance map in Maps.MapInstance.Lookup.Values) + foreach (MapInstance map in Maps.MapInstance.Lookup.Values) + { + if (x >= map.GetX() && x <= map.GetX() + Options.MapWidth * Options.TileWidth) { - if (x >= map.GetX() && x <= map.GetX() + Options.MapWidth * Options.TileWidth) + if (y >= map.GetY() && y <= map.GetY() + Options.MapHeight * Options.TileHeight) { - if (y >= map.GetY() && y <= map.GetY() + Options.MapHeight * Options.TileHeight) + //Remove the offsets to just be dealing with pixels within the map selected + x -= (int)map.GetX(); + y -= (int)map.GetY(); + + //transform pixel format to tile format + x /= Options.TileWidth; + y /= Options.TileHeight; + var mapId = map.Id; + + if (TryGetRealLocation(ref x, ref y, ref mapId)) { - //Remove the offsets to just be dealing with pixels within the map selected - x -= (int)map.GetX(); - y -= (int)map.GetY(); + foreach (var en in Globals.Entities) + { + if (en.Value == null || en.Value.MapId != mapId || en.Value is Projectile || en.Value is Resource || (en.Value.IsStealthed && !Globals.Me.IsInMyParty(en.Value.Id))) + { + continue; + } - //transform pixel format to tile format - x /= Options.TileWidth; - y /= Options.TileHeight; - var mapId = map.Id; + var intersectRect = FloatRect.Intersect(en.Value.WorldPos, targetRect); + if (intersectRect.Width * intersectRect.Height > bestAreaMatch) + { + bestAreaMatch = intersectRect.Width * intersectRect.Height; + bestMatch = en.Value; + } + } - if (TryGetRealLocation(ref x, ref y, ref mapId)) + foreach (MapInstance eventMap in Maps.MapInstance.Lookup.Values) { - foreach (var en in Globals.Entities) + foreach (var en in eventMap.LocalEntities) { - if (en.Value == null || en.Value.MapId != mapId || en.Value is Projectile || en.Value is Resource || (en.Value.IsStealthed && !Globals.Me.IsInMyParty(en.Value.Id))) + if (en.Value == null || en.Value.MapId != mapId || ((Event)en.Value).DisablePreview) { continue; } @@ -1951,646 +1968,667 @@ public bool TryTarget() bestMatch = en.Value; } } + } - foreach (MapInstance eventMap in Maps.MapInstance.Lookup.Values) - { - foreach (var en in eventMap.LocalEntities) - { - if (en.Value == null || en.Value.MapId != mapId || ((Event)en.Value).DisablePreview) - { - continue; - } - - var intersectRect = FloatRect.Intersect(en.Value.WorldPos, targetRect); - if (intersectRect.Width * intersectRect.Height > bestAreaMatch) - { - bestAreaMatch = intersectRect.Width * intersectRect.Height; - bestMatch = en.Value; - } - } - } - - if (bestMatch != null && bestMatch.Id != TargetIndex) - { - var targetType = bestMatch is Event ? 1 : 0; + if (bestMatch != null && bestMatch.Id != TargetIndex) + { + var targetType = bestMatch is Event ? 1 : 0; - SetTargetBox(bestMatch as Entity); + SetTargetBox(bestMatch as Entity); - if (bestMatch is Player) + if (bestMatch is Player) + { + //Select in admin window if open + if (Interface.Interface.GameUi.AdminWindowOpen()) { - //Select in admin window if open - if (Interface.Interface.GameUi.AdminWindowOpen()) - { - Interface.Interface.GameUi.AdminWindowSelectName(bestMatch.Name); - } + Interface.Interface.GameUi.AdminWindowSelectName(bestMatch.Name); } - - TargetType = targetType; - TargetIndex = bestMatch.Id; - - return true; } - if (!Globals.Database.StickyTarget) - { - // We've clicked off of our target and are allowed to clear it! - return ClearTarget(); - } + TargetType = targetType; + TargetIndex = bestMatch.Id; + + return true; } - return false; + if (!Globals.Database.StickyTarget) + { + // We've clicked off of our target and are allowed to clear it! + return ClearTarget(); + } } - } - } - - return false; - } - public bool TryTarget(IEntity entity, bool force = false) - { - //Check for taunt status if so don't allow to change target - for (var i = 0; i < Status.Count; i++) - { - if (Status[i].Type == SpellEffect.Taunt && !force) - { return false; } } + } - if (entity == null) + return false; + } + + public bool TryTarget(IEntity entity, bool force = false) + { + //Check for taunt status if so don't allow to change target + for (var i = 0; i < Status.Count; i++) + { + if (Status[i].Type == SpellEffect.Taunt && !force) { return false; } + } - // Are we already targetting this? - if (TargetBox != null && TargetBox.MyEntity == entity) - { - return true; - } + if (entity == null) + { + return false; + } - var targetType = entity is Event ? 1 : 0; + // Are we already targetting this? + if (TargetBox != null && TargetBox.MyEntity == entity) + { + return true; + } - if (entity is Player) - { - //Select in admin window if open - if (Interface.Interface.GameUi.AdminWindowOpen()) - { - Interface.Interface.GameUi.AdminWindowSelectName(entity.Name); - } - } + var targetType = entity is Event ? 1 : 0; - if (TargetIndex != entity.Id) + if (entity is Player) + { + //Select in admin window if open + if (Interface.Interface.GameUi.AdminWindowOpen()) { - SetTargetBox(entity as Entity); - TargetType = targetType; - TargetIndex = entity.Id; + Interface.Interface.GameUi.AdminWindowSelectName(entity.Name); } + } - return true; - + if (TargetIndex != entity.Id) + { + SetTargetBox(entity as Entity); + TargetType = targetType; + TargetIndex = entity.Id; } - public bool ClearTarget() + return true; + + } + + public bool ClearTarget() + { + SetTargetBox(null); + + if (TargetIndex == default && TargetType == -1) { - SetTargetBox(null); + return false; + } - if (TargetIndex == default && TargetType == -1) - { - return false; - } + TargetIndex = Guid.Empty; + TargetType = -1; + return true; + } - TargetIndex = Guid.Empty; - TargetType = -1; - return true; + /// + /// Attempts to pick up an item at the specified location. + /// + /// The Id of the map we are trying to loot from. + /// The X location on the current map. + /// The Y location on the current map. + /// The Unique Id of the specific item we want to pick up, leave to not specificy an item and pick up the first thing we can find. + /// Defines whether we only want to pick up the first item we can find when true, or all items when false. + /// + public bool TryPickupItem(Guid mapId, int tileIndex, Guid uniqueId = new(), bool firstOnly = false) + { + var map = Maps.MapInstance.Get(mapId); + if (map == null || tileIndex < 0 || tileIndex >= Options.MapWidth * Options.MapHeight) + { + return false; } - /// - /// Attempts to pick up an item at the specified location. - /// - /// The Id of the map we are trying to loot from. - /// The X location on the current map. - /// The Y location on the current map. - /// The Unique Id of the specific item we want to pick up, leave to not specificy an item and pick up the first thing we can find. - /// Defines whether we only want to pick up the first item we can find when true, or all items when false. - /// - public bool TryPickupItem(Guid mapId, int tileIndex, Guid uniqueId = new(), bool firstOnly = false) + // Are we trying to pick up anything in particular, or everything? + if (uniqueId != Guid.Empty || firstOnly) { - var map = Maps.MapInstance.Get(mapId); - if (map == null || tileIndex < 0 || tileIndex >= Options.MapWidth * Options.MapHeight) + if (!map.MapItems.ContainsKey(tileIndex) || map.MapItems[tileIndex].Count < 1) { return false; } - // Are we trying to pick up anything in particular, or everything? - if (uniqueId != Guid.Empty || firstOnly) + foreach (var item in map.MapItems[tileIndex]) { - if (!map.MapItems.ContainsKey(tileIndex) || map.MapItems[tileIndex].Count < 1) + // Check if we are trying to pick up a specific item, and if this is the one. + if (uniqueId != Guid.Empty && item.Id != uniqueId) { - return false; + continue; } - foreach (var item in map.MapItems[tileIndex]) - { - // Check if we are trying to pick up a specific item, and if this is the one. - if (uniqueId != Guid.Empty && item.Id != uniqueId) - { - continue; - } - - PacketSender.SendPickupItem(mapId, tileIndex, item.Id); - - return true; - } - } - else - { - // Let the server worry about what we can and can not pick up. - PacketSender.SendPickupItem(mapId, tileIndex, uniqueId); + PacketSender.SendPickupItem(mapId, tileIndex, item.Id); return true; } + } + else + { + // Let the server worry about what we can and can not pick up. + PacketSender.SendPickupItem(mapId, tileIndex, uniqueId); - return false; + return true; } - //Forumlas - public long GetNextLevelExperience() + return false; + } + + //Forumlas + public long GetNextLevelExperience() + { + return ExperienceToNextLevel; + } + + public override int CalculateAttackTime() + { + ItemBase weapon = null; + var attackTime = base.CalculateAttackTime(); + + var cls = ClassBase.Get(Class); + if (cls != null && cls.AttackSpeedModifier == 1) //Static { - return ExperienceToNextLevel; + attackTime = cls.AttackSpeedValue; } - public override int CalculateAttackTime() + if (this == Globals.Me) { - ItemBase weapon = null; - var attackTime = base.CalculateAttackTime(); - - var cls = ClassBase.Get(Class); - if (cls != null && cls.AttackSpeedModifier == 1) //Static + if (Options.WeaponIndex > -1 && + Options.WeaponIndex < Equipment.Length && + MyEquipment[Options.WeaponIndex] >= 0) { - attackTime = cls.AttackSpeedValue; + weapon = ItemBase.Get(Inventory[MyEquipment[Options.WeaponIndex]].ItemId); } - - if (this == Globals.Me) + } + else + { + if (Options.WeaponIndex > -1 && + Options.WeaponIndex < Equipment.Length && + Equipment[Options.WeaponIndex] != Guid.Empty) { - if (Options.WeaponIndex > -1 && - Options.WeaponIndex < Equipment.Length && - MyEquipment[Options.WeaponIndex] >= 0) - { - weapon = ItemBase.Get(Inventory[MyEquipment[Options.WeaponIndex]].ItemId); - } + weapon = ItemBase.Get(Equipment[Options.WeaponIndex]); } - else + } + + if (weapon != null) + { + if (weapon.AttackSpeedModifier == 1) // Static { - if (Options.WeaponIndex > -1 && - Options.WeaponIndex < Equipment.Length && - Equipment[Options.WeaponIndex] != Guid.Empty) - { - weapon = ItemBase.Get(Equipment[Options.WeaponIndex]); - } + attackTime = weapon.AttackSpeedValue; } - - if (weapon != null) + else if (weapon.AttackSpeedModifier == 2) //Percentage { - if (weapon.AttackSpeedModifier == 1) // Static - { - attackTime = weapon.AttackSpeedValue; - } - else if (weapon.AttackSpeedModifier == 2) //Percentage - { - attackTime = (int)(attackTime * (100f / weapon.AttackSpeedValue)); - } + attackTime = (int)(attackTime * (100f / weapon.AttackSpeedValue)); } - - return attackTime; } - /// - /// Calculate the attack time for the player as if they have a specified speed stat. - /// - /// - /// - public virtual int CalculateAttackTime(int speed) + return attackTime; + } + + /// + /// Calculate the attack time for the player as if they have a specified speed stat. + /// + /// + /// + public virtual int CalculateAttackTime(int speed) + { + return (int)(Options.MaxAttackRate + + (Options.MinAttackRate - Options.MaxAttackRate) * + (((float)Options.MaxStatValue - speed) / + Options.MaxStatValue)); + } + + //Movement Processing + private void ProcessDirectionalInput() + { + //Check if player is crafting + if (Globals.InCraft) { - return (int)(Options.MaxAttackRate + - (Options.MinAttackRate - Options.MaxAttackRate) * - (((float)Options.MaxStatValue - speed) / - Options.MaxStatValue)); + return; } - //Movement Processing - private void ProcessDirectionalInput() + //check if player is stunned or snared, if so don't let them move. + for (var n = 0; n < Status.Count; n++) { - //Check if player is crafting - if (Globals.InCraft) + if (Status[n].Type == SpellEffect.Stun || + Status[n].Type == SpellEffect.Snare || + Status[n].Type == SpellEffect.Sleep) { return; } + } - //check if player is stunned or snared, if so don't let them move. - for (var n = 0; n < Status.Count; n++) - { - if (Status[n].Type == SpellEffect.Stun || - Status[n].Type == SpellEffect.Snare || - Status[n].Type == SpellEffect.Sleep) - { - return; - } - } + //Check if the player is dashing, if so don't let them move. + if (Dashing != null || DashQueue.Count > 0 || DashTimer > Timing.Global.Milliseconds) + { + return; + } - //Check if the player is dashing, if so don't let them move. - if (Dashing != null || DashQueue.Count > 0 || DashTimer > Timing.Global.Milliseconds) - { - return; - } + if (IsAttacking && !Options.Instance.PlayerOpts.AllowCombatMovement) + { + return; + } - if (IsAttacking && !Options.Instance.PlayerOpts.AllowCombatMovement) - { - return; - } + Point position = new(X, Y); + IEntity blockedBy = null; - Point position = new(X, Y); - IEntity blockedBy = null; + if (MoveDir <= Direction.None || Globals.EventDialogs.Count != 0) + { + return; + } - if (MoveDir <= Direction.None || Globals.EventDialogs.Count != 0) - { - return; - } + //Try to move if able and not casting spells. + if (IsMoving || MoveTimer >= Timing.Global.Milliseconds || + (!Options.Combat.MovementCancelsCast && IsCasting)) + { + return; + } + + if (Options.Combat.MovementCancelsCast) + { + CastTime = 0; + } + + var dir = Dir; + var moveDir = MoveDir; - //Try to move if able and not casting spells. - if (IsMoving || MoveTimer >= Timing.Global.Milliseconds || - (!Options.Combat.MovementCancelsCast && IsCasting)) + var enableCrossingDiagonalBlocks = Options.Instance.MapOpts.EnableCrossingDiagonalBlocks; + + if (moveDir != Direction.None) + { + List possibleDirections = new(4) { moveDir }; + if (dir.IsAdjacent(moveDir)) { - return; + System.Console.WriteLine($"{dir} is adjacent to {moveDir}"); + possibleDirections.Add(dir); } - if (Options.Combat.MovementCancelsCast) + if (moveDir.IsDiagonal()) { - CastTime = 0; + possibleDirections.AddRange(moveDir.GetComponentDirections()); } - var dir = Dir; - var moveDir = MoveDir; - - var enableCrossingDiagonalBlocks = Options.Instance.MapOpts.EnableCrossingDiagonalBlocks; - - if (moveDir != Direction.None) + foreach (var possibleDirection in possibleDirections) { - List possibleDirections = new(4) { moveDir }; - if (dir.IsAdjacent(moveDir)) - { - System.Console.WriteLine($"{dir} is adjacent to {moveDir}"); - possibleDirections.Add(dir); - } - - if (moveDir.IsDiagonal()) + var delta = possibleDirection.GetDeltaPoint(); + var target = position + delta; + if (IsTileBlocked(target, Z, MapId, ref blockedBy) != -1) { - possibleDirections.AddRange(moveDir.GetComponentDirections()); + continue; } - foreach (var possibleDirection in possibleDirections) + if (!enableCrossingDiagonalBlocks && possibleDirection.IsDiagonal()) { - var delta = possibleDirection.GetDeltaPoint(); - var target = position + delta; - if (IsTileBlocked(target, Z, MapId, ref blockedBy) != -1) + if (possibleDirection.GetComponentDirections() + .Select(componentDirection => componentDirection.GetDeltaPoint() + position) + .All(componentTarget => IsTileBlocked(componentTarget, Z, MapId, ref blockedBy) != -1)) { continue; } - - if (!enableCrossingDiagonalBlocks && possibleDirection.IsDiagonal()) - { - if (possibleDirection.GetComponentDirections() - .Select(componentDirection => componentDirection.GetDeltaPoint() + position) - .All(componentTarget => IsTileBlocked(componentTarget, Z, MapId, ref blockedBy) != -1)) - { - continue; - } - } - - position.X += delta.X; - position.Y += delta.Y; - IsMoving = true; - Dir = possibleDirection; - - if (delta.X == 0) - { - OffsetX = 0; - } - else - { - OffsetX = delta.X > 0 ? -Options.TileWidth : Options.TileWidth; - } - - if (delta.Y == 0) - { - OffsetY = 0; - } - else - { - OffsetY = delta.Y > 0 ? -Options.TileHeight : Options.TileHeight; - } - - break; } - } - if (blockedBy != mLastBumpedEvent) - { - mLastBumpedEvent = null; - } + position.X += delta.X; + position.Y += delta.Y; + IsMoving = true; + Dir = possibleDirection; - if (IsMoving) - { - if (position.X < 0 || position.Y < 0 || position.X > Options.MapWidth - 1 || position.Y > Options.MapHeight - 1) + if (delta.X == 0) { - var gridX = Maps.MapInstance.Get(Globals.Me.MapId).GridX; - var gridY = Maps.MapInstance.Get(Globals.Me.MapId).GridY; - if (position.X < 0) - { - gridX--; - X = (byte)(Options.MapWidth - 1); - } - else if (position.X >= Options.MapWidth) - { - X = 0; - gridX++; - } - else - { - X = (byte)position.X; - } + OffsetX = 0; + } + else + { + OffsetX = delta.X > 0 ? -Options.TileWidth : Options.TileWidth; + } - if (position.Y < 0) - { - gridY--; - Y = (byte)(Options.MapHeight - 1); - } - else if (position.Y >= Options.MapHeight) - { - Y = 0; - gridY++; - } - else - { - Y = (byte)position.Y; - } + if (delta.Y == 0) + { + OffsetY = 0; + } + else + { + OffsetY = delta.Y > 0 ? -Options.TileHeight : Options.TileHeight; + } - if (MapId != Globals.MapGrid[gridX, gridY]) - { - MapId = Globals.MapGrid[gridX, gridY]; - FetchNewMaps(); - } + break; + } + } + + if (blockedBy != mLastBumpedEvent) + { + mLastBumpedEvent = null; + } + + if (IsMoving) + { + if (position.X < 0 || position.Y < 0 || position.X > Options.MapWidth - 1 || position.Y > Options.MapHeight - 1) + { + var gridX = Maps.MapInstance.Get(Globals.Me.MapId).GridX; + var gridY = Maps.MapInstance.Get(Globals.Me.MapId).GridY; + if (position.X < 0) + { + gridX--; + X = (byte)(Options.MapWidth - 1); + } + else if (position.X >= Options.MapWidth) + { + X = 0; + gridX++; } else { X = (byte)position.X; - Y = (byte)position.Y; } - TryToChangeDimension(); - PacketSender.SendMove(); - MoveTimer = (Timing.Global.Milliseconds) + (long)GetMovementTime(); - } - else - { - if (MoveDir != Dir) + if (position.Y < 0) + { + gridY--; + Y = (byte)(Options.MapHeight - 1); + } + else if (position.Y >= Options.MapHeight) + { + Y = 0; + gridY++; + } + else { - Dir = MoveDir; - PacketSender.SendDirection(Dir); - PickLastDirection(Dir); + Y = (byte)position.Y; } - if (blockedBy != null && mLastBumpedEvent != blockedBy && blockedBy is Event) + if (MapId != Globals.MapGrid[gridX, gridY]) { - PacketSender.SendBumpEvent(blockedBy.MapId, blockedBy.Id); - mLastBumpedEvent = blockedBy as Entity; + MapId = Globals.MapGrid[gridX, gridY]; + FetchNewMaps(); } } - } + else + { + X = (byte)position.X; + Y = (byte)position.Y; + } - public void FetchNewMaps() + TryToChangeDimension(); + PacketSender.SendMove(); + MoveTimer = (Timing.Global.Milliseconds) + (long)GetMovementTime(); + } + else { - if (Globals.MapGridWidth == 0 || Globals.MapGridHeight == 0) + if (MoveDir != Dir) { - return; + Dir = MoveDir; + PacketSender.SendDirection(Dir); + PickLastDirection(Dir); + } + + if (blockedBy != null && mLastBumpedEvent != blockedBy && blockedBy is Event) + { + PacketSender.SendBumpEvent(blockedBy.MapId, blockedBy.Id); + mLastBumpedEvent = blockedBy as Entity; } + } + } - PacketSender.SendNeedMapForGrid(); + public void FetchNewMaps() + { + if (Globals.MapGridWidth == 0 || Globals.MapGridHeight == 0) + { + return; } - public override void DrawEquipment(string filename, Color renderColor) + PacketSender.SendNeedMapForGrid(); + } + + public override void DrawEquipment(string filename, Color renderColor) + { + //check if player is stunned or snared, if so don't let them move. + for (var n = 0; n < Status.Count; n++) { - //check if player is stunned or snared, if so don't let them move. - for (var n = 0; n < Status.Count; n++) + if (Status[n].Type == SpellEffect.Transform) { - if (Status[n].Type == SpellEffect.Transform) - { - return; - } + return; } - - base.DrawEquipment(filename, renderColor); } - //Override of the original function, used for rendering the color of a player based on rank - public override void DrawName(Color textColor, Color borderColor, Color backgroundColor) + base.DrawEquipment(filename, renderColor); + } + + //Override of the original function, used for rendering the color of a player based on rank + public override void DrawName(Color textColor, Color borderColor, Color backgroundColor) + { + if (textColor == null) { - if (textColor == null) + switch (AccessLevel) { - switch (AccessLevel) - { - case Access.Moderator: - textColor = CustomColors.Names.Players["Moderator"].Name; - borderColor = CustomColors.Names.Players["Moderator"].Outline; - backgroundColor = CustomColors.Names.Players["Moderator"].Background; - break; + case Access.Moderator: + textColor = CustomColors.Names.Players["Moderator"].Name; + borderColor = CustomColors.Names.Players["Moderator"].Outline; + backgroundColor = CustomColors.Names.Players["Moderator"].Background; + break; - case Access.Admin: - textColor = CustomColors.Names.Players["Admin"].Name; - borderColor = CustomColors.Names.Players["Admin"].Outline; - backgroundColor = CustomColors.Names.Players["Admin"].Background; - break; + case Access.Admin: + textColor = CustomColors.Names.Players["Admin"].Name; + borderColor = CustomColors.Names.Players["Admin"].Outline; + backgroundColor = CustomColors.Names.Players["Admin"].Background; + break; - case Access.None: - default: - textColor = CustomColors.Names.Players["Normal"].Name; - borderColor = CustomColors.Names.Players["Normal"].Outline; - backgroundColor = CustomColors.Names.Players["Normal"].Background; - break; - } + case Access.None: + default: + textColor = CustomColors.Names.Players["Normal"].Name; + borderColor = CustomColors.Names.Players["Normal"].Outline; + backgroundColor = CustomColors.Names.Players["Normal"].Background; + break; } + } - var customColorOverride = NameColor; - if (customColorOverride != null) + var customColorOverride = NameColor; + if (customColorOverride != null) + { + //We don't want to override the default colors if the color is transparent! + if (customColorOverride.A != 0) { - //We don't want to override the default colors if the color is transparent! - if (customColorOverride.A != 0) - { - textColor = customColorOverride; - } + textColor = customColorOverride; } + } - if (Globals.Me.Id != Id) + if (Globals.Me.Id != Id) + { + // Party member names + if (Globals.Me.IsInMyParty(this) && CustomColors.Names.Players.TryGetValue(nameof(Party), out var partyColors)) { - // Party member names - if (Globals.Me.IsInMyParty(this) && CustomColors.Names.Players.TryGetValue(nameof(Party), out var partyColors)) - { - textColor = partyColors.Name; - borderColor = partyColors.Outline; - backgroundColor = partyColors.Background; - } - // Guildies - else if (Globals.Me.IsInGuild && Guild == Globals.Me.Guild && CustomColors.Names.Players.TryGetValue(nameof(Guild), out var guildColors)) - { - textColor = guildColors.Name; - borderColor = guildColors.Outline; - backgroundColor = guildColors.Background; - } + textColor = partyColors.Name; + borderColor = partyColors.Outline; + backgroundColor = partyColors.Background; + } + // Guildies + else if (Globals.Me.IsInGuild && Guild == Globals.Me.Guild && CustomColors.Names.Players.TryGetValue(nameof(Guild), out var guildColors)) + { + textColor = guildColors.Name; + borderColor = guildColors.Outline; + backgroundColor = guildColors.Background; + } - // Enemies in PvP - if (!Globals.Me.IsAllyOf(this) && Globals.Me.MapInstance.ZoneType != MapZone.Safe && CustomColors.Names.Players.TryGetValue("Hostile", out var hostileColors)) - { - textColor = hostileColors.Name; - borderColor = hostileColors.Outline; - backgroundColor = hostileColors.Background; - } + // Enemies in PvP + if (!Globals.Me.IsAllyOf(this) && Globals.Me.MapInstance.ZoneType != MapZone.Safe && CustomColors.Names.Players.TryGetValue("Hostile", out var hostileColors)) + { + textColor = hostileColors.Name; + borderColor = hostileColors.Outline; + backgroundColor = hostileColors.Background; } + } + + DrawNameAndLabels(textColor, borderColor, backgroundColor); + } + + public override bool IsAllyOf(Player en) + { + if (base.IsAllyOf(en)) + { + return true; + } + + return IsInMyParty(en) || IsInMyGuild(en) || en.MapInstance.ZoneType == MapZone.Safe; + } + + private void DrawNameAndLabels(Color textColor, Color borderColor, Color backgroundColor) + { + base.DrawName(textColor, borderColor, backgroundColor); + DrawLabels(HeaderLabel.Text, 0, HeaderLabel.Color, textColor, borderColor, backgroundColor); + DrawLabels(FooterLabel.Text, 1, FooterLabel.Color, textColor, borderColor, backgroundColor); + DrawGuildName(textColor, borderColor, backgroundColor); + } - DrawNameAndLabels(textColor, borderColor, backgroundColor); + public virtual void DrawGuildName(Color textColor, Color? borderColor = default, Color? backgroundColor = default) + { + var guildLabel = Guild?.Trim(); + if (!ShouldDrawName || string.IsNullOrWhiteSpace(guildLabel) || !Options.Instance.Guild.ShowGuildNameTagsOverMembers) + { + return; } - public override bool IsAllyOf(Player en) + if (IsStealthed && !IsInMyParty(Globals.Me)) { - if (base.IsAllyOf(en)) - { - return true; - } + // Do not render if the party is stealthed and not in the local player's party + return; + } - return IsInMyParty(en) || IsInMyGuild(en) || en.MapInstance.ZoneType == MapZone.Safe; + if (MapInstance == default) + { + return; } - private void DrawNameAndLabels(Color textColor, Color borderColor, Color backgroundColor) + var textSize = Graphics.Renderer.MeasureText(guildLabel, Graphics.EntityNameFont, 1); + + var x = (int)Math.Ceiling(Origin.X); + var y = GetLabelLocation(LabelType.Guild); + + backgroundColor ??= Color.Transparent; + if (backgroundColor != Color.Transparent) { - base.DrawName(textColor, borderColor, backgroundColor); - DrawLabels(HeaderLabel.Text, 0, HeaderLabel.Color, textColor, borderColor, backgroundColor); - DrawLabels(FooterLabel.Text, 1, FooterLabel.Color, textColor, borderColor, backgroundColor); - DrawGuildName(textColor, borderColor, backgroundColor); + Graphics.DrawGameTexture( + Graphics.Renderer.GetWhiteTexture(), + new FloatRect(0, 0, 1, 1), + new FloatRect(x - textSize.X / 2f - 4, y, textSize.X + 8, textSize.Y), + backgroundColor + ); } - public virtual void DrawGuildName(Color textColor, Color? borderColor = default, Color? backgroundColor = default) + borderColor ??= Color.Transparent; + Graphics.Renderer.DrawString( + guildLabel, + Graphics.EntityNameFont, + x - (int)Math.Ceiling(textSize.X / 2f), + (int)y, + 1, + Color.FromArgb(textColor.ToArgb()), + true, + default, + Color.FromArgb(borderColor.ToArgb()) + ); + } + + protected override bool ShouldDrawHpBar + { + get { - var guildLabel = Guild?.Trim(); - if (!ShouldDrawName || string.IsNullOrWhiteSpace(guildLabel) || !Options.Instance.Guild.ShowGuildNameTagsOverMembers) + if (ShouldNotDrawHpBar) { - return; + return false; } - if (IsStealthed && !IsInMyParty(Globals.Me)) + if (IsHovered) { - // Do not render if the party is stealthed and not in the local player's party - return; + return true; } - if (MapInstance == default) + var me = Globals.Me; + + if (Globals.Database.MyOverheadHpBar && Id == me.Id) { - return; + return true; } - var textSize = Graphics.Renderer.MeasureText(guildLabel, Graphics.EntityNameFont, 1); + if (Globals.Database.PlayerOverheadHpBar && Id != me.Id) + { + return true; + } - var x = (int)Math.Ceiling(Origin.X); - var y = GetLabelLocation(LabelType.Guild); + if (Globals.Database.PartyMemberOverheadHpBar && me.IsInMyParty(this)) + { + return true; + } - backgroundColor ??= Color.Transparent; - if (backgroundColor != Color.Transparent) + if (Globals.Database.FriendOverheadHpBar && me.IsFriend(this)) { - Graphics.DrawGameTexture( - Graphics.Renderer.GetWhiteTexture(), - new FloatRect(0, 0, 1, 1), - new FloatRect(x - textSize.X / 2f - 4, y, textSize.X + 8, textSize.Y), - backgroundColor - ); + return true; } - borderColor ??= Color.Transparent; - Graphics.Renderer.DrawString( - guildLabel, - Graphics.EntityNameFont, - x - (int)Math.Ceiling(textSize.X / 2f), - (int)y, - 1, - Color.FromArgb(textColor.ToArgb()), - true, - default, - Color.FromArgb(borderColor.ToArgb()) - ); + return Globals.Database.GuildMemberOverheadHpBar && me.IsGuildMate(this); } + } - protected override bool ShouldDrawHpBar + public void DrawTargets() + { + foreach (var en in Globals.Entities) { - get + if (en.Value == null) { - if (ShouldNotDrawHpBar) - { - return false; - } - - if (IsHovered) - { - return true; - } - - var me = Globals.Me; - - if (Globals.Database.MyOverheadHpBar && Id == me.Id) - { - return true; - } + continue; + } - if (Globals.Database.PlayerOverheadHpBar && Id != me.Id) - { - return true; - } + if (en.Value.IsHidden) + { + continue; + } - if (Globals.Database.PartyMemberOverheadHpBar && me.IsInMyParty(this)) - { - return true; - } + if (en.Value.IsStealthed && (!(en.Value is Player player) || !Globals.Me.IsInMyParty(player))) + { + continue; + } - if (Globals.Database.FriendOverheadHpBar && me.IsFriend(this)) - { - return true; - } + if (en.Value is Projectile || en.Value is Resource) + { + continue; + } - return Globals.Database.GuildMemberOverheadHpBar && me.IsGuildMate(this); + if (TargetType != 0 || TargetIndex != en.Value.Id) + { + continue; } + + en.Value.DrawTarget((int)Enums.TargetType.Selected); + AutoTurnToTarget(en.Value); } - public void DrawTargets() + foreach (MapInstance eventMap in Maps.MapInstance.Lookup.Values) { - foreach (var en in Globals.Entities) + foreach (var en in eventMap.LocalEntities) { if (en.Value == null) { continue; } - if (en.Value.IsHidden) + if (en.Value.MapId != eventMap.Id) { continue; } - if (en.Value.IsStealthed && (!(en.Value is Player player) || !Globals.Me.IsInMyParty(player))) + if (en.Value is Event eventEntity && eventEntity.DisablePreview) + { + continue; + } + + if (en.Value.IsHidden) { continue; } - if (en.Value is Projectile || en.Value is Resource) + if (en.Value.IsStealthed && (!(en.Value is Player player) || !Globals.Me.IsInMyParty(player))) { continue; } - if (TargetType != 0 || TargetIndex != en.Value.Id) + if (TargetType != 1 || TargetIndex != en.Value.Id) { continue; } @@ -2598,59 +2636,46 @@ public void DrawTargets() en.Value.DrawTarget((int)Enums.TargetType.Selected); AutoTurnToTarget(en.Value); } + } - foreach (MapInstance eventMap in Maps.MapInstance.Lookup.Values) + if (!Interface.Interface.MouseHitGui()) + { + var mouseInWorld = Graphics.ConvertToWorldPoint(Globals.InputManager.GetMousePosition()); + foreach (MapInstance map in Maps.MapInstance.Lookup.Values) { - foreach (var en in eventMap.LocalEntities) + if (mouseInWorld.X >= map.GetX() && mouseInWorld.X <= map.GetX() + Options.MapWidth * Options.TileWidth) { - if (en.Value == null) - { - continue; - } - - if (en.Value.MapId != eventMap.Id) - { - continue; - } - - if (en.Value is Event eventEntity && eventEntity.DisablePreview) - { - continue; - } - - if (en.Value.IsHidden) - { - continue; - } - - if (en.Value.IsStealthed && (!(en.Value is Player player) || !Globals.Me.IsInMyParty(player))) + if (mouseInWorld.Y >= map.GetY() && + mouseInWorld.Y <= map.GetY() + Options.MapHeight * Options.TileHeight) { - continue; - } + var mapId = map.Id; - if (TargetType != 1 || TargetIndex != en.Value.Id) - { - continue; - } + foreach (var en in Globals.Entities) + { + if (en.Value == null) + { + continue; + } - en.Value.DrawTarget((int)Enums.TargetType.Selected); - AutoTurnToTarget(en.Value); - } - } + if (en.Value.MapId == mapId && + !en.Value.HideName && + (!en.Value.IsStealthed || + en.Value is Player player && Globals.Me.IsInMyParty(player)) && + en.Value.WorldPos.Contains(mouseInWorld.X, mouseInWorld.Y)) + { + if (!(en.Value is Projectile || en.Value is Resource)) + { + if (TargetType != 0 || TargetIndex != en.Value.Id) + { + en.Value.DrawTarget((int)Enums.TargetType.Hover); + } + } + } + } - if (!Interface.Interface.MouseHitGui()) - { - var mouseInWorld = Graphics.ConvertToWorldPoint(Globals.InputManager.GetMousePosition()); - foreach (MapInstance map in Maps.MapInstance.Lookup.Values) - { - if (mouseInWorld.X >= map.GetX() && mouseInWorld.X <= map.GetX() + Options.MapWidth * Options.TileWidth) - { - if (mouseInWorld.Y >= map.GetY() && - mouseInWorld.Y <= map.GetY() + Options.MapHeight * Options.TileHeight) + foreach (MapInstance eventMap in Maps.MapInstance.Lookup.Values) { - var mapId = map.Id; - - foreach (var en in Globals.Entities) + foreach (var en in eventMap.LocalEntities) { if (en.Value == null) { @@ -2658,144 +2683,117 @@ public void DrawTargets() } if (en.Value.MapId == mapId && - !en.Value.HideName && + !(en.Value as Event).DisablePreview && + !en.Value.IsHidden && (!en.Value.IsStealthed || en.Value is Player player && Globals.Me.IsInMyParty(player)) && en.Value.WorldPos.Contains(mouseInWorld.X, mouseInWorld.Y)) { - if (!(en.Value is Projectile || en.Value is Resource)) - { - if (TargetType != 0 || TargetIndex != en.Value.Id) - { - en.Value.DrawTarget((int)Enums.TargetType.Hover); - } - } - } - } - - foreach (MapInstance eventMap in Maps.MapInstance.Lookup.Values) - { - foreach (var en in eventMap.LocalEntities) - { - if (en.Value == null) - { - continue; - } - - if (en.Value.MapId == mapId && - !(en.Value as Event).DisablePreview && - !en.Value.IsHidden && - (!en.Value.IsStealthed || - en.Value is Player player && Globals.Me.IsInMyParty(player)) && - en.Value.WorldPos.Contains(mouseInWorld.X, mouseInWorld.Y)) + if (TargetType != 1 || TargetIndex != en.Value.Id) { - if (TargetType != 1 || TargetIndex != en.Value.Id) - { - en.Value.DrawTarget((int)Enums.TargetType.Hover); - } + en.Value.DrawTarget((int)Enums.TargetType.Hover); } } } - - break; } + + break; } } } } + } - private class TargetInfo - { - public long LastTimeSelected; + private class TargetInfo + { + public long LastTimeSelected; - public int DistanceTo; - } + public int DistanceTo; + } - private void TurnAround() + private void TurnAround() + { + // If players hold the 'TurnAround' Control Key and tap to any direction, they will turn on their own axis. + for (var direction = 0; direction < Options.Instance.MapOpts.MovementDirections; direction++) { - // If players hold the 'TurnAround' Control Key and tap to any direction, they will turn on their own axis. - for (var direction = 0; direction < Options.Instance.MapOpts.MovementDirections; direction++) + if (!Controls.KeyDown(Control.TurnAround) || direction != (int)Globals.Me.MoveDir || IsTurnAroundWhileCastingDisabled) { - if (!Controls.KeyDown(Control.TurnAround) || direction != (int)Globals.Me.MoveDir || IsTurnAroundWhileCastingDisabled) - { - continue; - } + continue; + } - // Turn around and hold the player in place if the requested direction is different from the current one. - if (!Globals.Me.IsMoving && Dir != Globals.Me.MoveDir) - { - Dir = Globals.Me.MoveDir; - PacketSender.SendDirection(Dir); - Globals.Me.MoveDir = Direction.None; - PickLastDirection(Dir); - } + // Turn around and hold the player in place if the requested direction is different from the current one. + if (!Globals.Me.IsMoving && Dir != Globals.Me.MoveDir) + { + Dir = Globals.Me.MoveDir; + PacketSender.SendDirection(Dir); + Globals.Me.MoveDir = Direction.None; + PickLastDirection(Dir); + } - // Hold the player in place if the requested direction is the same as the current one. - if (!Globals.Me.IsMoving && Dir == Globals.Me.MoveDir) - { - Globals.Me.MoveDir = Direction.None; - } + // Hold the player in place if the requested direction is the same as the current one. + if (!Globals.Me.IsMoving && Dir == Globals.Me.MoveDir) + { + Globals.Me.MoveDir = Direction.None; } } - - // Checks if the target is at the opposite direction of the current player's direction. - // The comparison also takes into account whether diagonal movement is enabled or not. - private static bool IsTargetAtOppositeDirection(Direction currentDir, Direction targetDir) + } + + // Checks if the target is at the opposite direction of the current player's direction. + // The comparison also takes into account whether diagonal movement is enabled or not. + private static bool IsTargetAtOppositeDirection(Direction currentDir, Direction targetDir) + { + if (Options.Instance.MapOpts.EnableDiagonalMovement) { - if (Options.Instance.MapOpts.EnableDiagonalMovement) + // If diagonal movement is disabled, check opposite directions on 4 directions. + switch (currentDir) { - // If diagonal movement is disabled, check opposite directions on 4 directions. - switch (currentDir) - { - case Direction.Up: - return targetDir == Direction.Down || targetDir == Direction.DownLeft || - targetDir == Direction.DownRight; + case Direction.Up: + return targetDir == Direction.Down || targetDir == Direction.DownLeft || + targetDir == Direction.DownRight; - case Direction.Down: - return targetDir == Direction.Up || targetDir == Direction.UpLeft || - targetDir == Direction.UpRight; + case Direction.Down: + return targetDir == Direction.Up || targetDir == Direction.UpLeft || + targetDir == Direction.UpRight; - case Direction.Left: - return targetDir == Direction.Right || targetDir == Direction.UpRight || - targetDir == Direction.DownRight; + case Direction.Left: + return targetDir == Direction.Right || targetDir == Direction.UpRight || + targetDir == Direction.DownRight; - case Direction.Right: - return targetDir == Direction.Left || targetDir == Direction.UpLeft || - targetDir == Direction.DownLeft; + case Direction.Right: + return targetDir == Direction.Left || targetDir == Direction.UpLeft || + targetDir == Direction.DownLeft; - default: - if (!Options.Instance.MapOpts.EnableDiagonalMovement) - { - return false; - } + default: + if (!Options.Instance.MapOpts.EnableDiagonalMovement) + { + return false; + } - break; - } + break; } + } - // If diagonal movement is enabled, check opposite directions on 8 directions. - switch (currentDir) - { - case Direction.UpLeft: - return targetDir == Direction.DownRight || targetDir == Direction.Right || - targetDir == Direction.Down; + // If diagonal movement is enabled, check opposite directions on 8 directions. + switch (currentDir) + { + case Direction.UpLeft: + return targetDir == Direction.DownRight || targetDir == Direction.Right || + targetDir == Direction.Down; - case Direction.UpRight: - return targetDir == Direction.DownLeft || targetDir == Direction.Left || - targetDir == Direction.Down; + case Direction.UpRight: + return targetDir == Direction.DownLeft || targetDir == Direction.Left || + targetDir == Direction.Down; - case Direction.DownLeft: - return targetDir == Direction.UpRight || targetDir == Direction.Right || - targetDir == Direction.Up; + case Direction.DownLeft: + return targetDir == Direction.UpRight || targetDir == Direction.Right || + targetDir == Direction.Up; - case Direction.DownRight: - return targetDir == Direction.UpLeft || targetDir == Direction.Left || - targetDir == Direction.Up; + case Direction.DownRight: + return targetDir == Direction.UpLeft || targetDir == Direction.Left || + targetDir == Direction.Up; - default: - return false; - } + default: + return false; } } - } diff --git a/Intersect.Client/Entities/Projectiles/Projectile.cs b/Intersect.Client/Entities/Projectiles/Projectile.cs index ebf0a610c5..9aeff6dad7 100644 --- a/Intersect.Client/Entities/Projectiles/Projectile.cs +++ b/Intersect.Client/Entities/Projectiles/Projectile.cs @@ -7,758 +7,756 @@ using Intersect.Utilities; using MapAttribute = Intersect.Enums.MapAttribute; -namespace Intersect.Client.Entities.Projectiles +namespace Intersect.Client.Entities.Projectiles; + + +public partial class Projectile : Entity { - public partial class Projectile : Entity - { + private bool _isDisposing; - private bool _isDisposing; + private bool _isLoaded; - private bool _isLoaded; + private readonly object _lock = new object(); - private readonly object _lock = new object(); + private ProjectileBase _myBase; - private ProjectileBase _myBase; + private Guid _owner; - private Guid _owner; + private int _quantity; - private int _quantity; + private int _spawnCount; - private int _spawnCount; + private int _spawnedAmount; - private int _spawnedAmount; + private long _spawnTime; - private long _spawnTime; + private int _totalSpawns; - private int _totalSpawns; + private Guid _projectileId; - private Guid _projectileId; + // Individual Spawns + private ProjectileSpawns[] _spawns; - // Individual Spawns - private ProjectileSpawns[] _spawns; + private Guid _targetId; - private Guid _targetId; + private int _lastTargetX = -1; - private int _lastTargetX = -1; + private int _lastTargetY = -1; - private int _lastTargetY = -1; + private Guid _lastTargetMapId = Guid.Empty; - private Guid _lastTargetMapId = Guid.Empty; + /// + /// The constructor for the inherated projectile class + /// + public Projectile(Guid id, ProjectileEntityPacket packet) : base(id, packet, EntityType.Projectile) + { + Vital[(int)Enums.Vital.Health] = 1; + MaxVital[(int)Enums.Vital.Health] = 1; + HideName = true; + Passable = true; + IsMoving = true; + } - /// - /// The constructor for the inherated projectile class - /// - public Projectile(Guid id, ProjectileEntityPacket packet) : base(id, packet, EntityType.Projectile) + public override void Load(EntityPacket packet) + { + if (_isLoaded) { - Vital[(int)Enums.Vital.Health] = 1; - MaxVital[(int)Enums.Vital.Health] = 1; - HideName = true; - Passable = true; - IsMoving = true; + return; } - public override void Load(EntityPacket packet) + base.Load(packet); + var pkt = (ProjectileEntityPacket)packet; + _projectileId = pkt.ProjectileId; + Dir = (Direction)pkt.ProjectileDirection; + _targetId = pkt.TargetId; + _owner = pkt.OwnerId; + _myBase = ProjectileBase.Get(_projectileId); + if (_myBase != null) { - if (_isLoaded) - { - return; - } - - base.Load(packet); - var pkt = (ProjectileEntityPacket)packet; - _projectileId = pkt.ProjectileId; - Dir = (Direction)pkt.ProjectileDirection; - _targetId = pkt.TargetId; - _owner = pkt.OwnerId; - _myBase = ProjectileBase.Get(_projectileId); - if (_myBase != null) + for (var x = 0; x < ProjectileBase.SPAWN_LOCATIONS_WIDTH; x++) { - for (var x = 0; x < ProjectileBase.SPAWN_LOCATIONS_WIDTH; x++) + for (var y = 0; y < ProjectileBase.SPAWN_LOCATIONS_HEIGHT; y++) { - for (var y = 0; y < ProjectileBase.SPAWN_LOCATIONS_HEIGHT; y++) + for (var d = 0; d < ProjectileBase.MAX_PROJECTILE_DIRECTIONS; d++) { - for (var d = 0; d < ProjectileBase.MAX_PROJECTILE_DIRECTIONS; d++) + if (_myBase.SpawnLocations[x, y].Directions[d] == true) { - if (_myBase.SpawnLocations[x, y].Directions[d] == true) - { - _totalSpawns++; - } + _totalSpawns++; } } } - - _totalSpawns *= _myBase.Quantity; } - _spawns = new ProjectileSpawns[_totalSpawns]; - _isLoaded = true; + _totalSpawns *= _myBase.Quantity; } - /// - /// Disposes of the resources used by this instance, preventing any further use. - /// - public override void Dispose() + _spawns = new ProjectileSpawns[_totalSpawns]; + _isLoaded = true; + } + + /// + /// Disposes of the resources used by this instance, preventing any further use. + /// + public override void Dispose() + { + if (!_isDisposing) { - if (!_isDisposing) + lock (_lock) { - lock (_lock) - { - _isDisposing = true; + _isDisposing = true; - // Perform a final update if no projectiles have been spawned. - if (_spawnedAmount == 0) - { - Update(); - } + // Perform a final update if no projectiles have been spawned. + if (_spawnedAmount == 0) + { + Update(); + } - if (_spawns != null) + if (_spawns != null) + { + foreach (var s in _spawns) { - foreach (var s in _spawns) - { - s?.Anim?.DisposeNextDraw(); - } + s?.Anim?.DisposeNextDraw(); } - - GC.SuppressFinalize(this); } + + GC.SuppressFinalize(this); } } + } - /// - public override bool CanBeAttacked + /// + public override bool CanBeAttacked + { + get { - get - { - return false; - } + return false; } + } - /// - /// Determines the appropriate animation data index for the current spawn wave of the projectile. - /// This method iterates through the available animations defined in the projectile's base configuration, - /// selecting the one whose spawn range encompasses the current quantity of spawns. - /// - /// The index of the animation data to use for the current spawn wave. - private int FindSpawnAnimationData() + /// + /// Determines the appropriate animation data index for the current spawn wave of the projectile. + /// This method iterates through the available animations defined in the projectile's base configuration, + /// selecting the one whose spawn range encompasses the current quantity of spawns. + /// + /// The index of the animation data to use for the current spawn wave. + private int FindSpawnAnimationData() + { + var start = 0; + for (var i = 0; i < _myBase.Animations.Count; i++) { - var start = 0; - for (var i = 0; i < _myBase.Animations.Count; i++) + var end = _myBase.Animations[i].SpawnRange; + if (_quantity >= start && _quantity < end) { - var end = _myBase.Animations[i].SpawnRange; - if (_quantity >= start && _quantity < end) - { - return i; - } - - start = end; + return i; } - // If no suitable animation is found (e.g., developer(s) fucked up the animation ranges), default to the last animation. - // This serves as a fallback to prevent crashes or undefined behavior in case of misconfiguration. - return _myBase.Animations.Count - 1; + start = end; } - /// - /// Adds projectile spawns based on predefined spawn locations and directions. - /// - private void AddProjectileSpawns() - { - var spawn = FindSpawnAnimationData(); - var animBase = AnimationBase.Get(_myBase.Animations[spawn].AnimationId); + // If no suitable animation is found (e.g., developer(s) fucked up the animation ranges), default to the last animation. + // This serves as a fallback to prevent crashes or undefined behavior in case of misconfiguration. + return _myBase.Animations.Count - 1; + } - for (var x = 0; x < ProjectileBase.SPAWN_LOCATIONS_WIDTH; x++) + /// + /// Adds projectile spawns based on predefined spawn locations and directions. + /// + private void AddProjectileSpawns() + { + var spawn = FindSpawnAnimationData(); + var animBase = AnimationBase.Get(_myBase.Animations[spawn].AnimationId); + + for (var x = 0; x < ProjectileBase.SPAWN_LOCATIONS_WIDTH; x++) + { + for (var y = 0; y < ProjectileBase.SPAWN_LOCATIONS_HEIGHT; y++) { - for (var y = 0; y < ProjectileBase.SPAWN_LOCATIONS_HEIGHT; y++) + for (var d = 0; d < ProjectileBase.MAX_PROJECTILE_DIRECTIONS; d++) { - for (var d = 0; d < ProjectileBase.MAX_PROJECTILE_DIRECTIONS; d++) + // Check if the current direction is enabled for spawning at this location. + if (_myBase.SpawnLocations[x, y].Directions[d] == true) { - // Check if the current direction is enabled for spawning at this location. - if (_myBase.SpawnLocations[x, y].Directions[d] == true) + // Calculate the spawn position and direction for the new projectile + var s = new ProjectileSpawns( + FindProjectileRotationDir(Dir, (Direction)d), + (byte)(X + FindProjectileRotation(Dir, x - 2, y - 2, true)), + (byte)(Y + FindProjectileRotation(Dir, x - 2, y - 2, false)), Z, MapId, animBase, + _myBase.Animations[spawn].AutoRotate, _myBase, this + ); + + _spawns[_spawnedAmount] = s; + if (Collided(_spawnedAmount)) { - // Calculate the spawn position and direction for the new projectile - var s = new ProjectileSpawns( - FindProjectileRotationDir(Dir, (Direction)d), - (byte)(X + FindProjectileRotation(Dir, x - 2, y - 2, true)), - (byte)(Y + FindProjectileRotation(Dir, x - 2, y - 2, false)), Z, MapId, animBase, - _myBase.Animations[spawn].AutoRotate, _myBase, this - ); - - _spawns[_spawnedAmount] = s; - if (Collided(_spawnedAmount)) - { - TryRemoveSpawn(_spawnedAmount); - _spawnCount--; - } - - // Add the new spawn to the array and increment counters - _spawnedAmount++; - _spawnCount++; + TryRemoveSpawn(_spawnedAmount); + _spawnCount--; } + + // Add the new spawn to the array and increment counters + _spawnedAmount++; + _spawnCount++; } } } - - // Increment the quantity of projectiles spawned and update the spawn time based on the delay - _quantity++; - _spawnTime = Timing.Global.Milliseconds + _myBase.Delay; } - /// - /// Finds the projectile rotation value based on the direction, position and the axis. - /// - /// The direction of the projectile. - /// The x-coordinate value. - /// The y-coordinate value. - /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. - /// The rotation value for the specified axis based on the direction. - private static int FindProjectileRotation(Direction direction, int x, int y, bool isXAxis) + // Increment the quantity of projectiles spawned and update the spawn time based on the delay + _quantity++; + _spawnTime = Timing.Global.Milliseconds + _myBase.Delay; + } + + /// + /// Finds the projectile rotation value based on the direction, position and the axis. + /// + /// The direction of the projectile. + /// The x-coordinate value. + /// The y-coordinate value. + /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. + /// The rotation value for the specified axis based on the direction. + private static int FindProjectileRotation(Direction direction, int x, int y, bool isXAxis) + { + if (isXAxis) { - if (isXAxis) + return direction switch { - return direction switch - { - Direction.Up => x, - Direction.Down => -x, - Direction.Left or Direction.UpLeft or Direction.DownLeft => y, - Direction.Right or Direction.UpRight or Direction.DownRight => -y, - _ => x, - }; - } - else + Direction.Up => x, + Direction.Down => -x, + Direction.Left or Direction.UpLeft or Direction.DownLeft => y, + Direction.Right or Direction.UpRight or Direction.DownRight => -y, + _ => x, + }; + } + else + { + return direction switch { - return direction switch - { - Direction.Up => y, - Direction.Down => -y, - Direction.Left or Direction.UpLeft or Direction.DownLeft => -x, - Direction.Right or Direction.UpRight or Direction.DownRight => x, - _ => y, - }; - } + Direction.Up => y, + Direction.Down => -y, + Direction.Left or Direction.UpLeft or Direction.DownLeft => -x, + Direction.Right or Direction.UpRight or Direction.DownRight => x, + _ => y, + }; } + } - private static Direction FindProjectileRotationDir(Direction entityDir, Direction projectionDir) => - (Direction)ProjectileBase.ProjectileRotationDir[(int)entityDir * ProjectileBase.MAX_PROJECTILE_DIRECTIONS + (int)projectionDir]; - - /// - /// Calculates the projectile range based on the given direction, range, and axis. - /// - /// The direction of the projectile. - /// The range of the projectile. - /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. - /// The calculated range value. - private static float GetRange(Direction direction, float range, bool isXAxis) + private static Direction FindProjectileRotationDir(Direction entityDir, Direction projectionDir) => + (Direction)ProjectileBase.ProjectileRotationDir[(int)entityDir * ProjectileBase.MAX_PROJECTILE_DIRECTIONS + (int)projectionDir]; + + /// + /// Calculates the projectile range based on the given direction, range, and axis. + /// + /// The direction of the projectile. + /// The range of the projectile. + /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. + /// The calculated range value. + private static float GetRange(Direction direction, float range, bool isXAxis) + { + if (isXAxis) { - if (isXAxis) + return direction switch { - return direction switch - { - Direction.Left or Direction.UpLeft or Direction.DownLeft => -range, - Direction.Right or Direction.UpRight or Direction.DownRight => range, - _ => 0, - }; - } - else + Direction.Left or Direction.UpLeft or Direction.DownLeft => -range, + Direction.Right or Direction.UpRight or Direction.DownRight => range, + _ => 0, + }; + } + else + { + return direction switch { - return direction switch - { - Direction.Up or Direction.UpLeft or Direction.UpRight => -range, - Direction.Down or Direction.DownLeft or Direction.DownRight => range, - _ => 0, - }; - } + Direction.Up or Direction.UpLeft or Direction.UpRight => -range, + Direction.Down or Direction.DownLeft or Direction.DownRight => range, + _ => 0, + }; } + } - /// - /// Gets the displacement of the projectile during projection - /// - /// The displacement from the co-ordinates if placed on a Options.TileHeight grid. - private float GetDisplacement(long spawnTime) - { - var elapsedTime = Timing.Global.Milliseconds - spawnTime; - var displacementPercent = elapsedTime / (float)_myBase.Speed; - var calculatedDisplacement = displacementPercent * Options.TileHeight * _myBase.Range; + /// + /// Gets the displacement of the projectile during projection + /// + /// The displacement from the co-ordinates if placed on a Options.TileHeight grid. + private float GetDisplacement(long spawnTime) + { + var elapsedTime = Timing.Global.Milliseconds - spawnTime; + var displacementPercent = elapsedTime / (float)_myBase.Speed; + var calculatedDisplacement = displacementPercent * Options.TileHeight * _myBase.Range; + + // Ensure displacement does not exceed the maximum range of the projectile + var maxDisplacement = Options.TileHeight * _myBase.Range; + return Math.Min(calculatedDisplacement, maxDisplacement); + } - // Ensure displacement does not exceed the maximum range of the projectile - var maxDisplacement = Options.TileHeight * _myBase.Range; - return Math.Min(calculatedDisplacement, maxDisplacement); + /// + /// Overwrite updating the offsets for projectile movement. + /// + public override bool Update() + { + if (_myBase == null) + { + return false; } - /// - /// Overwrite updating the offsets for projectile movement. - /// - public override bool Update() + lock (_lock) { - if (_myBase == null) + var map = MapId; + var y = Y; + + if (!_isDisposing && _quantity < _myBase.Quantity && _spawnTime < Timing.Global.Milliseconds) { - return false; + AddProjectileSpawns(); } - lock (_lock) + if (IsMoving) { - var map = MapId; - var y = Y; - - if (!_isDisposing && _quantity < _myBase.Quantity && _spawnTime < Timing.Global.Milliseconds) + for (var s = 0; s < _spawnedAmount; s++) { - AddProjectileSpawns(); - } - - if (IsMoving) - { - for (var s = 0; s < _spawnedAmount; s++) + var spawn = _spawns[s]; + + if (spawn != null && Maps.MapInstance.Get(spawn.SpawnMapId) != null) { - var spawn = _spawns[s]; - - if (spawn != null && Maps.MapInstance.Get(spawn.SpawnMapId) != null) + if (_targetId != Guid.Empty && _targetId != _owner && Globals.Entities.ContainsKey(_targetId) && (_myBase.HomingBehavior || _myBase.DirectShotBehavior)) { - if (_targetId != Guid.Empty && _targetId != _owner && Globals.Entities.ContainsKey(_targetId) && (_myBase.HomingBehavior || _myBase.DirectShotBehavior)) - { - var target = Globals.Entities[_targetId]; - _lastTargetX = target.X; - _lastTargetY = target.Y; - _lastTargetMapId = target.MapId; - - spawn.OffsetX = GetProjectileLerping(spawn, true); - spawn.OffsetY = GetProjectileLerping(spawn, false); - SetProjectileRotation(spawn); - - if (_myBase.DirectShotBehavior) - { - _targetId = Guid.Empty; - } - } - else if (_lastTargetX != -1 && _lastTargetY != -1) - { - spawn.OffsetX = GetProjectileLerping(spawn, true); - spawn.OffsetY = GetProjectileLerping(spawn, false); - SetProjectileRotation(spawn); - } - else + var target = Globals.Entities[_targetId]; + _lastTargetX = target.X; + _lastTargetY = target.Y; + _lastTargetMapId = target.MapId; + + spawn.OffsetX = GetProjectileLerping(spawn, true); + spawn.OffsetY = GetProjectileLerping(spawn, false); + SetProjectileRotation(spawn); + + if (_myBase.DirectShotBehavior) { - spawn.OffsetX = GetRange(spawn.Dir, GetDisplacement(spawn.SpawnTime), true); - spawn.OffsetY = GetRange(spawn.Dir, GetDisplacement(spawn.SpawnTime), false); - spawn.Anim.SetRotation(false); + _targetId = Guid.Empty; } + } + else if (_lastTargetX != -1 && _lastTargetY != -1) + { + spawn.OffsetX = GetProjectileLerping(spawn, true); + spawn.OffsetY = GetProjectileLerping(spawn, false); + SetProjectileRotation(spawn); + } + else + { + spawn.OffsetX = GetRange(spawn.Dir, GetDisplacement(spawn.SpawnTime), true); + spawn.OffsetY = GetRange(spawn.Dir, GetDisplacement(spawn.SpawnTime), false); + spawn.Anim.SetRotation(false); + } - var spawnMapId = Maps.MapInstance.Get(spawn.SpawnMapId); - var spawnX = spawnMapId.GetX() + spawn.SpawnX * Options.TileWidth + spawn.OffsetX + Options.TileWidth / 2; - var spawnY = spawnMapId.GetY() + spawn.SpawnY * Options.TileHeight + spawn.OffsetY + Options.TileHeight / 2; - var spawnDirection = spawn.AutoRotate ? spawn.Dir : Direction.Up; + var spawnMapId = Maps.MapInstance.Get(spawn.SpawnMapId); + var spawnX = spawnMapId.GetX() + spawn.SpawnX * Options.TileWidth + spawn.OffsetX + Options.TileWidth / 2; + var spawnY = spawnMapId.GetY() + spawn.SpawnY * Options.TileHeight + spawn.OffsetY + Options.TileHeight / 2; + var spawnDirection = spawn.AutoRotate ? spawn.Dir : Direction.Up; - spawn.Anim.SetPosition(spawnX, spawnY, X, Y, MapId, spawnDirection, spawn.Z); - spawn.Anim.Update(); - } + spawn.Anim.SetPosition(spawnX, spawnY, X, Y, MapId, spawnDirection, spawn.Z); + spawn.Anim.Update(); } } - - CheckForCollision(); } - return true; + CheckForCollision(); } - /// - /// Calculates the offset for the projectile spawn position based on the target map and spawn location. - /// - /// The projectile spawn information. - /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. - /// The calculated offset value. - private float GetProjectileOffset(ProjectileSpawns spawn, bool isXAxis) + return true; + } + + /// + /// Calculates the offset for the projectile spawn position based on the target map and spawn location. + /// + /// The projectile spawn information. + /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. + /// The calculated offset value. + private float GetProjectileOffset(ProjectileSpawns spawn, bool isXAxis) + { + if (_lastTargetMapId == Guid.Empty || _lastTargetMapId == spawn.SpawnMapId || !Maps.MapInstance.TryGet(spawn.SpawnMapId, out var map)) { - if (_lastTargetMapId == Guid.Empty || _lastTargetMapId == spawn.SpawnMapId || !Maps.MapInstance.TryGet(spawn.SpawnMapId, out var map)) - { - return isXAxis ? _lastTargetX - spawn.SpawnX : _lastTargetY - spawn.SpawnY; - } + return isXAxis ? _lastTargetX - spawn.SpawnX : _lastTargetY - spawn.SpawnY; + } - for (var y = map.GridY - 1; y <= map.GridY + 1; y++) + for (var y = map.GridY - 1; y <= map.GridY + 1; y++) + { + for (var x = map.GridX - 1; x <= map.GridX + 1; x++) { - for (var x = map.GridX - 1; x <= map.GridX + 1; x++) + if (x < 0 || x >= Globals.MapGrid.GetLength(0) || y < 0 || y >= Globals.MapGrid.GetLength(1)) + { + continue; + } + + if (Globals.MapGrid[x, y] != _lastTargetMapId || Globals.MapGrid[x, y] == Guid.Empty) + { + continue; + } + + if (isXAxis) // Horizontal (X) calculation { - if (x < 0 || x >= Globals.MapGrid.GetLength(0) || y < 0 || y >= Globals.MapGrid.GetLength(1)) + var leftSide = x == map.GridX - 1; + var rightSide = x == map.GridX + 1; + + if (leftSide) { - continue; + return _lastTargetX - Options.MapWidth - spawn.SpawnX; } - if (Globals.MapGrid[x, y] != _lastTargetMapId || Globals.MapGrid[x, y] == Guid.Empty) + if (rightSide) { - continue; + return _lastTargetX + Options.MapWidth - spawn.SpawnX; } + } + else // Vertical (Y) calculation + { + var topSide = y == map.GridY + 1; + var bottomSide = y == map.GridY - 1; - if (isXAxis) // Horizontal (X) calculation + if (topSide) { - var leftSide = x == map.GridX - 1; - var rightSide = x == map.GridX + 1; - - if (leftSide) - { - return _lastTargetX - Options.MapWidth - spawn.SpawnX; - } - - if (rightSide) - { - return _lastTargetX + Options.MapWidth - spawn.SpawnX; - } + return _lastTargetY + Options.MapHeight - spawn.SpawnY; } - else // Vertical (Y) calculation - { - var topSide = y == map.GridY + 1; - var bottomSide = y == map.GridY - 1; - - if (topSide) - { - return _lastTargetY + Options.MapHeight - spawn.SpawnY; - } - if (bottomSide) - { - return _lastTargetY - Options.MapHeight - spawn.SpawnY; - } + if (bottomSide) + { + return _lastTargetY - Options.MapHeight - spawn.SpawnY; } } } - - return isXAxis ? _lastTargetX - spawn.SpawnX : _lastTargetY - spawn.SpawnY; } - /// - /// Calculates the interpolated (lerped) position value for a projectile along the X or Y axis. - /// - /// The spawn information of the projectile, including its initial position and spawn time. - /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. - /// The interpolated position value for the projectile on the specified axis, taking into account the projectile's travel direction, speed, and elapsed time since spawning. - /// - /// This method determines the projectile's current position by interpolating between its initial offset and its desired position at the current time. - /// It calculates the direction and magnitude of the projectile's movement, normalizes this to obtain a unit vector in the direction of movement, - /// and then applies linear interpolation based on the elapsed time since the projectile was spawned. - /// The interpolation factor is clamped to ensure that the projectile does not overshoot its target position. - /// - private float GetProjectileLerping(ProjectileSpawns spawn, bool isXAxis) - { - var (directionX, directionY) = (GetProjectileOffset(spawn, true), GetProjectileOffset(spawn, false)); - var distance = MathF.Sqrt(directionX * directionX + directionY * directionY); - if (distance == 0) return 0; - - var valueToLerp = (isXAxis ? directionX : directionY) / distance; - var offset = isXAxis ? spawn.OffsetX : spawn.OffsetY; - var desiredValue = GetDisplacement(spawn.SpawnTime + Options.Instance.Processing.ProjectileUpdateInterval) * valueToLerp; - var totalDuration = (float)_myBase.Range * (_myBase.Speed / Options.TileHeight); - var elapsedTime = Timing.Global.Milliseconds - spawn.SpawnTime; - var lerpFactor = Utilities.MathHelper.Clamp(elapsedTime / totalDuration, 0f, 1f); - - // Dynamically calculated lerp factor - return (1 - lerpFactor) * offset + lerpFactor * desiredValue; - } + return isXAxis ? _lastTargetX - spawn.SpawnX : _lastTargetY - spawn.SpawnY; + } - /// - /// Sets the rotation of a projectile based on its spawn information. - /// - /// The spawn information of the projectile, including its current animation state and position. - /// - /// This method calculates the angle between the projectile's current position and its target, - /// converting the angle from radians to degrees and adjusting it by 90 degrees to align with the game's coordinate system. - /// The calculated angle is then applied to the projectile's animation state to visually orient the projectile towards its target. - /// - private void SetProjectileRotation(ProjectileSpawns spawn) + /// + /// Calculates the interpolated (lerped) position value for a projectile along the X or Y axis. + /// + /// The spawn information of the projectile, including its initial position and spawn time. + /// True for horizontal (X-axis), false for vertical (Y-axis) calculation. + /// The interpolated position value for the projectile on the specified axis, taking into account the projectile's travel direction, speed, and elapsed time since spawning. + /// + /// This method determines the projectile's current position by interpolating between its initial offset and its desired position at the current time. + /// It calculates the direction and magnitude of the projectile's movement, normalizes this to obtain a unit vector in the direction of movement, + /// and then applies linear interpolation based on the elapsed time since the projectile was spawned. + /// The interpolation factor is clamped to ensure that the projectile does not overshoot its target position. + /// + private float GetProjectileLerping(ProjectileSpawns spawn, bool isXAxis) + { + var (directionX, directionY) = (GetProjectileOffset(spawn, true), GetProjectileOffset(spawn, false)); + var distance = MathF.Sqrt(directionX * directionX + directionY * directionY); + if (distance == 0) return 0; + + var valueToLerp = (isXAxis ? directionX : directionY) / distance; + var offset = isXAxis ? spawn.OffsetX : spawn.OffsetY; + var desiredValue = GetDisplacement(spawn.SpawnTime + Options.Instance.Processing.ProjectileUpdateInterval) * valueToLerp; + var totalDuration = (float)_myBase.Range * (_myBase.Speed / Options.TileHeight); + var elapsedTime = Timing.Global.Milliseconds - spawn.SpawnTime; + var lerpFactor = Utilities.MathHelper.Clamp(elapsedTime / totalDuration, 0f, 1f); + + // Dynamically calculated lerp factor + return (1 - lerpFactor) * offset + lerpFactor * desiredValue; + } + + /// + /// Sets the rotation of a projectile based on its spawn information. + /// + /// The spawn information of the projectile, including its current animation state and position. + /// + /// This method calculates the angle between the projectile's current position and its target, + /// converting the angle from radians to degrees and adjusting it by 90 degrees to align with the game's coordinate system. + /// The calculated angle is then applied to the projectile's animation state to visually orient the projectile towards its target. + /// + private void SetProjectileRotation(ProjectileSpawns spawn) + { + var (directionX, directionY) = (GetProjectileOffset(spawn, true), GetProjectileOffset(spawn, false)); + var angle = (float)(Math.Atan2(directionY, directionX) * (180.0 / Math.PI) + 90); + spawn.Anim.SetRotation(angle); + } + + /// + /// Checks for collision of the projectile with other entities or map boundaries. + /// + public void CheckForCollision() + { + if (_spawnCount == 0 && _quantity > _myBase.Quantity) { - var (directionX, directionY) = (GetProjectileOffset(spawn, true), GetProjectileOffset(spawn, false)); - var angle = (float)(Math.Atan2(directionY, directionX) * (180.0 / Math.PI) + 90); - spawn.Anim.SetRotation(angle); + Globals.Entities[Id].Dispose(); + return; } - /// - /// Checks for collision of the projectile with other entities or map boundaries. - /// - public void CheckForCollision() + for (var i = 0; i < _spawnedAmount && i < _spawns.Length; i++) { - if (_spawnCount == 0 && _quantity > _myBase.Quantity) + var projectileSpawn = _spawns[i]; + if (projectileSpawn == null || Timing.Global.Milliseconds <= projectileSpawn.TransmissionTimer) { - Globals.Entities[Id].Dispose(); - return; + continue; } - for (var i = 0; i < _spawnedAmount && i < _spawns.Length; i++) + if (!Maps.MapInstance.TryGet(projectileSpawn.MapId, out var spawnMap)) { - var projectileSpawn = _spawns[i]; - if (projectileSpawn == null || Timing.Global.Milliseconds <= projectileSpawn.TransmissionTimer) - { - continue; - } - - if (!Maps.MapInstance.TryGet(projectileSpawn.MapId, out var spawnMap)) - { - continue; - } + continue; + } - float newx = projectileSpawn.X; - float newy = projectileSpawn.Y; + float newx = projectileSpawn.X; + float newy = projectileSpawn.Y; - if (_myBase.HomingBehavior || _myBase.DirectShotBehavior) - { - if (_targetId != Guid.Empty && _targetId != _owner || _lastTargetX != -1 && _lastTargetY != -1 && _lastTargetMapId != Guid.Empty) - { - var (deltaX, deltaY) = (GetProjectileOffset(projectileSpawn, true), GetProjectileOffset(projectileSpawn, false)); - float distance = MathF.Sqrt(deltaX * deltaX + deltaY * deltaY); - float xFactor = deltaX / distance; - float yFactor = deltaY / distance; - newx += xFactor; - newy += yFactor; - } - } - else + if (_myBase.HomingBehavior || _myBase.DirectShotBehavior) + { + if (_targetId != Guid.Empty && _targetId != _owner || _lastTargetX != -1 && _lastTargetY != -1 && _lastTargetMapId != Guid.Empty) { - newx += GetRange(projectileSpawn.Dir, 1, true); - newy += GetRange(projectileSpawn.Dir, 1, false); + var (deltaX, deltaY) = (GetProjectileOffset(projectileSpawn, true), GetProjectileOffset(projectileSpawn, false)); + float distance = MathF.Sqrt(deltaX * deltaX + deltaY * deltaY); + float xFactor = deltaX / distance; + float yFactor = deltaY / distance; + newx += xFactor; + newy += yFactor; } + } + else + { + newx += GetRange(projectileSpawn.Dir, 1, true); + newy += GetRange(projectileSpawn.Dir, 1, false); + } - AdjustPositionOnMapBoundaries(ref newx, ref newy, ref spawnMap); + AdjustPositionOnMapBoundaries(ref newx, ref newy, ref spawnMap); - projectileSpawn.X = (int)newx; - projectileSpawn.Y = (int)newy; - projectileSpawn.MapId = spawnMap.Id; - projectileSpawn.Distance++; - projectileSpawn.TransmissionTimer = Timing.Global.MillisecondsOffset + (long)(_myBase.Speed / (float)_myBase.Range); + projectileSpawn.X = (int)newx; + projectileSpawn.Y = (int)newy; + projectileSpawn.MapId = spawnMap.Id; + projectileSpawn.Distance++; + projectileSpawn.TransmissionTimer = Timing.Global.MillisecondsOffset + (long)(_myBase.Speed / (float)_myBase.Range); - var killSpawn = Collided(i) || projectileSpawn.Distance >= _myBase.Range || - newx < 0 || newx >= Options.MapWidth || newy < 0 || - newy >= Options.MapHeight; + var killSpawn = Collided(i) || projectileSpawn.Distance >= _myBase.Range || + newx < 0 || newx >= Options.MapWidth || newy < 0 || + newy >= Options.MapHeight; - // Check for map boundaries and remove the spawn if it goes out of bounds. - if (killSpawn) - { - TryRemoveSpawn(i); - _spawnCount--; + // Check for map boundaries and remove the spawn if it goes out of bounds. + if (killSpawn) + { + TryRemoveSpawn(i); + _spawnCount--; - continue; - } + continue; + } + + // Check for Z-Dimension + if (!killSpawn && spawnMap.Attributes != null && + projectileSpawn.X >= 0 && projectileSpawn.Y >= 0 && projectileSpawn.X < spawnMap.Attributes.GetLength(0) && + projectileSpawn.Y < spawnMap.Attributes.GetLength(1)) + { + var attribute = spawnMap.Attributes[projectileSpawn.X, projectileSpawn.Y]; - // Check for Z-Dimension - if (!killSpawn && spawnMap.Attributes != null && - projectileSpawn.X >= 0 && projectileSpawn.Y >= 0 && projectileSpawn.X < spawnMap.Attributes.GetLength(0) && - projectileSpawn.Y < spawnMap.Attributes.GetLength(1)) + if (attribute != null && attribute.Type == MapAttribute.ZDimension) { - var attribute = spawnMap.Attributes[projectileSpawn.X, projectileSpawn.Y]; + var zDimensionAttribute = (MapZDimensionAttribute)attribute; - if (attribute != null && attribute.Type == MapAttribute.ZDimension) + // If the Z dimension attribute specifies a blocked level that matches the projectile's current Z level, + // mark the projectile for destruction. + if (zDimensionAttribute.BlockedLevel > 0 && projectileSpawn.Z == zDimensionAttribute.BlockedLevel - 1) { - var zDimensionAttribute = (MapZDimensionAttribute)attribute; - - // If the Z dimension attribute specifies a blocked level that matches the projectile's current Z level, - // mark the projectile for destruction. - if (zDimensionAttribute.BlockedLevel > 0 && projectileSpawn.Z == zDimensionAttribute.BlockedLevel - 1) - { - killSpawn = true; - } + killSpawn = true; + } - // If the Z dimension attribute specifies a gateway to another level, - // adjust the projectile's Z level to the specified gateway level. - if (zDimensionAttribute.GatewayTo > 0) - { - projectileSpawn.Z = zDimensionAttribute.GatewayTo - 1; - } + // If the Z dimension attribute specifies a gateway to another level, + // adjust the projectile's Z level to the specified gateway level. + if (zDimensionAttribute.GatewayTo > 0) + { + projectileSpawn.Z = zDimensionAttribute.GatewayTo - 1; } } + } - if (killSpawn) - { - TryRemoveSpawn(i); - _spawnCount--; - } + if (killSpawn) + { + TryRemoveSpawn(i); + _spawnCount--; } } + } - /// - /// Adjusts the position of a projectile on the map boundaries, potentially changing its map instance. - /// - /// The new x-coordinate of the projectile. - /// The new y-coordinate of the projectile. - /// The map instance where the projectile is spawned. This may be updated if the projectile crosses map boundaries. - /// - /// This method checks if the projectile crosses the boundaries of its current map. If it does, it attempts to move the projectile - /// to the adjacent map in the direction it crossed the boundary. This includes handling corner cases where the projectile crosses - /// at the corners of the map, potentially moving it diagonally to a new map. The new position of the projectile is adjusted to - /// visually reflect its entry point into the adjacent map. - /// - private static void AdjustPositionOnMapBoundaries(ref float newx, ref float newy, ref Maps.MapInstance spawnMap) - { - int MapWidth = Options.MapWidth; - int MapHeight = Options.MapHeight; + /// + /// Adjusts the position of a projectile on the map boundaries, potentially changing its map instance. + /// + /// The new x-coordinate of the projectile. + /// The new y-coordinate of the projectile. + /// The map instance where the projectile is spawned. This may be updated if the projectile crosses map boundaries. + /// + /// This method checks if the projectile crosses the boundaries of its current map. If it does, it attempts to move the projectile + /// to the adjacent map in the direction it crossed the boundary. This includes handling corner cases where the projectile crosses + /// at the corners of the map, potentially moving it diagonally to a new map. The new position of the projectile is adjusted to + /// visually reflect its entry point into the adjacent map. + /// + private static void AdjustPositionOnMapBoundaries(ref float newx, ref float newy, ref Maps.MapInstance spawnMap) + { + int MapWidth = Options.MapWidth; + int MapHeight = Options.MapHeight; - // Determine if the projectile crosses any of the map boundaries. - bool crossesLeftBoundary = MathF.Floor(newx) < 0; - bool crossesRightBoundary = MathF.Ceiling(newx) > MapWidth - 1; - bool crossesTopBoundary = MathF.Floor(newy) < 0; - bool crossesBottomBoundary = MathF.Ceiling(newy) > MapHeight - 1; + // Determine if the projectile crosses any of the map boundaries. + bool crossesLeftBoundary = MathF.Floor(newx) < 0; + bool crossesRightBoundary = MathF.Ceiling(newx) > MapWidth - 1; + bool crossesTopBoundary = MathF.Floor(newy) < 0; + bool crossesBottomBoundary = MathF.Ceiling(newy) > MapHeight - 1; - // Handle corner cases: crossing boundaries at the corners of the map. - if (crossesLeftBoundary && crossesTopBoundary) + // Handle corner cases: crossing boundaries at the corners of the map. + if (crossesLeftBoundary && crossesTopBoundary) + { + // Move to the map diagonally up-left if possible. + if (Maps.MapInstance.TryGet(spawnMap.Up, out var upMap) && + Maps.MapInstance.TryGet(upMap.Left, out var upLeftMap)) { - // Move to the map diagonally up-left if possible. - if (Maps.MapInstance.TryGet(spawnMap.Up, out var upMap) && - Maps.MapInstance.TryGet(upMap.Left, out var upLeftMap)) - { - spawnMap = upLeftMap; - newx = MapWidth - 1; - newy = MapHeight - 1; - } + spawnMap = upLeftMap; + newx = MapWidth - 1; + newy = MapHeight - 1; } - else if (crossesRightBoundary && crossesTopBoundary) + } + else if (crossesRightBoundary && crossesTopBoundary) + { + // Move to the map diagonally up-right if possible. + if (Maps.MapInstance.TryGet(spawnMap.Up, out var upMap) && + Maps.MapInstance.TryGet(upMap.Right, out var upRightMap)) { - // Move to the map diagonally up-right if possible. - if (Maps.MapInstance.TryGet(spawnMap.Up, out var upMap) && - Maps.MapInstance.TryGet(upMap.Right, out var upRightMap)) - { - spawnMap = upRightMap; - newx = 0; - newy = MapHeight - 1; - } + spawnMap = upRightMap; + newx = 0; + newy = MapHeight - 1; } - else if (crossesLeftBoundary && crossesBottomBoundary) + } + else if (crossesLeftBoundary && crossesBottomBoundary) + { + // Move to the map diagonally down-left if possible. + if (Maps.MapInstance.TryGet(spawnMap.Down, out var downMap) && + Maps.MapInstance.TryGet(downMap.Left, out var downLeftMap)) { - // Move to the map diagonally down-left if possible. - if (Maps.MapInstance.TryGet(spawnMap.Down, out var downMap) && - Maps.MapInstance.TryGet(downMap.Left, out var downLeftMap)) - { - spawnMap = downLeftMap; - newx = MapWidth - 1; - newy = 0; - } + spawnMap = downLeftMap; + newx = MapWidth - 1; + newy = 0; } - else if (crossesRightBoundary && crossesBottomBoundary) + } + else if (crossesRightBoundary && crossesBottomBoundary) + { + // Move to the map diagonally down-right if possible. + if (Maps.MapInstance.TryGet(spawnMap.Down, out var downMap) && + Maps.MapInstance.TryGet(downMap.Right, out var downRightMap)) { - // Move to the map diagonally down-right if possible. - if (Maps.MapInstance.TryGet(spawnMap.Down, out var downMap) && - Maps.MapInstance.TryGet(downMap.Right, out var downRightMap)) - { - spawnMap = downRightMap; - newx = 0; - newy = 0; - } + spawnMap = downRightMap; + newx = 0; + newy = 0; } - // Handle cases where the projectile crosses one boundary. - else if (crossesLeftBoundary) + } + // Handle cases where the projectile crosses one boundary. + else if (crossesLeftBoundary) + { + // Move to the map on the left if possible. + if (Maps.MapInstance.TryGet(spawnMap.Left, out var leftMap)) { - // Move to the map on the left if possible. - if (Maps.MapInstance.TryGet(spawnMap.Left, out var leftMap)) - { - spawnMap = leftMap; - newx = MapWidth - 1; - } + spawnMap = leftMap; + newx = MapWidth - 1; } - else if (crossesRightBoundary) + } + else if (crossesRightBoundary) + { + // Move to the map on the right if possible. + if (Maps.MapInstance.TryGet(spawnMap.Right, out var rightMap)) { - // Move to the map on the right if possible. - if (Maps.MapInstance.TryGet(spawnMap.Right, out var rightMap)) - { - spawnMap = rightMap; - newx = 0; - } + spawnMap = rightMap; + newx = 0; } - else if (crossesTopBoundary) + } + else if (crossesTopBoundary) + { + // Move to the map above if possible. + if (Maps.MapInstance.TryGet(spawnMap.Up, out var upMap)) { - // Move to the map above if possible. - if (Maps.MapInstance.TryGet(spawnMap.Up, out var upMap)) - { - spawnMap = upMap; - newy = MapHeight - 1; - } + spawnMap = upMap; + newy = MapHeight - 1; } - else if (crossesBottomBoundary) + } + else if (crossesBottomBoundary) + { + // Move to the map below if possible. + if (Maps.MapInstance.TryGet(spawnMap.Down, out var downMap)) { - // Move to the map below if possible. - if (Maps.MapInstance.TryGet(spawnMap.Down, out var downMap)) - { - spawnMap = downMap; - newy = 0; - } + spawnMap = downMap; + newy = 0; } } + } - /// - /// Determines if a projectile spawn has collided with an entity, resource, or map block. - /// - /// The index of the projectile spawn in the _spawns array. - /// True if the projectile spawn has collided and should be destroyed; otherwise, false. - private bool Collided(int i) + /// + /// Determines if a projectile spawn has collided with an entity, resource, or map block. + /// + /// The index of the projectile spawn in the _spawns array. + /// True if the projectile spawn has collided and should be destroyed; otherwise, false. + private bool Collided(int i) + { + var killSpawn = false; + IEntity? blockedBy = default; + var spawn = _spawns[i]; + + // Check if the tile at the projectile's location is blocked. + var tileBlocked = Globals.Me.IsTileBlocked( + delta: new Point(spawn.X, spawn.Y), + z: Z, + mapId: spawn.MapId, + blockedBy: ref blockedBy, + ignoreAliveResources: spawn.ProjectileBase.IgnoreActiveResources, + ignoreDeadResources: spawn.ProjectileBase.IgnoreExhaustedResources, + ignoreNpcAvoids: true, + projectileTrigger: true + ); + + switch (tileBlocked) { - var killSpawn = false; - IEntity? blockedBy = default; - var spawn = _spawns[i]; - - // Check if the tile at the projectile's location is blocked. - var tileBlocked = Globals.Me.IsTileBlocked( - delta: new Point(spawn.X, spawn.Y), - z: Z, - mapId: spawn.MapId, - blockedBy: ref blockedBy, - ignoreAliveResources: spawn.ProjectileBase.IgnoreActiveResources, - ignoreDeadResources: spawn.ProjectileBase.IgnoreExhaustedResources, - ignoreNpcAvoids: true, - projectileTrigger: true - ); - - switch (tileBlocked) - { - case -1: // No collision detected - return killSpawn; - case -6: // Collision with an entity other than the owner - if (blockedBy != default && blockedBy.Id != _owner && Globals.Entities.ContainsKey(blockedBy.Id)) - { - if (blockedBy is Resource) - { - killSpawn = true; - } - } - break; - case -2: // Collision with a map block - if (!spawn.ProjectileBase.IgnoreMapBlocks) - { - killSpawn = true; - } - break; - case -3: // Collision with a Z-dimension block - if (!spawn.ProjectileBase.IgnoreZDimension) + case -1: // No collision detected + return killSpawn; + case -6: // Collision with an entity other than the owner + if (blockedBy != default && blockedBy.Id != _owner && Globals.Entities.ContainsKey(blockedBy.Id)) + { + if (blockedBy is Resource) { killSpawn = true; } - break; - case -5: // Collision with an unspecified block type or out of map bounds + } + break; + case -2: // Collision with a map block + if (!spawn.ProjectileBase.IgnoreMapBlocks) + { killSpawn = true; - break; - } - - return killSpawn; + } + break; + case -3: // Collision with a Z-dimension block + if (!spawn.ProjectileBase.IgnoreZDimension) + { + killSpawn = true; + } + break; + case -5: // Collision with an unspecified block type or out of map bounds + killSpawn = true; + break; } - /// - /// Rendering all of the individual projectiles from a singular spawn to a map. - /// - public override void Draw() + return killSpawn; + } + + /// + /// Rendering all of the individual projectiles from a singular spawn to a map. + /// + public override void Draw() + { + if (Maps.MapInstance.Get(MapId) == null || !Globals.GridMaps.Contains(MapId)) { - if (Maps.MapInstance.Get(MapId) == null || !Globals.GridMaps.Contains(MapId)) - { - return; - } + return; } + } - public void SpawnDead(int spawnIndex) + public void SpawnDead(int spawnIndex) + { + if (spawnIndex < _spawnedAmount && _spawns[spawnIndex] != null) { - if (spawnIndex < _spawnedAmount && _spawns[spawnIndex] != null) - { - TryRemoveSpawn(spawnIndex); - } + TryRemoveSpawn(spawnIndex); } + } - private void TryRemoveSpawn(int spawnIndex) + private void TryRemoveSpawn(int spawnIndex) + { + if (spawnIndex < _spawnedAmount && _spawns[spawnIndex] != null) { - if (spawnIndex < _spawnedAmount && _spawns[spawnIndex] != null) - { - _spawns[spawnIndex].Dispose(); - _spawns[spawnIndex] = null; - } + _spawns[spawnIndex].Dispose(); + _spawns[spawnIndex] = null; } - } } diff --git a/Intersect.Client/Entities/Projectiles/ProjectileSpawns.cs b/Intersect.Client/Entities/Projectiles/ProjectileSpawns.cs index 221fa1f4a6..3ef6167961 100644 --- a/Intersect.Client/Entities/Projectiles/ProjectileSpawns.cs +++ b/Intersect.Client/Entities/Projectiles/ProjectileSpawns.cs @@ -2,76 +2,74 @@ using Intersect.GameObjects; using Intersect.Utilities; -namespace Intersect.Client.Entities.Projectiles -{ +namespace Intersect.Client.Entities.Projectiles; - public partial class ProjectileSpawns - { - public Animation Anim; +public partial class ProjectileSpawns +{ - public bool AutoRotate; + public Animation Anim; - public Direction Dir; + public bool AutoRotate; - public int Distance; + public Direction Dir; - public Guid MapId; + public int Distance; - //Clientside variables - public float OffsetX; + public Guid MapId; - public float OffsetY; + //Clientside variables + public float OffsetX; - public ProjectileBase ProjectileBase; + public float OffsetY; - public Guid SpawnMapId; + public ProjectileBase ProjectileBase; - public long SpawnTime = Timing.Global.Milliseconds; + public Guid SpawnMapId; - public int SpawnX; + public long SpawnTime = Timing.Global.Milliseconds; - public int SpawnY; + public int SpawnX; - public long TransmissionTimer = Timing.Global.Milliseconds; + public int SpawnY; - public int X; + public long TransmissionTimer = Timing.Global.Milliseconds; - public int Y; + public int X; - public int Z; + public int Y; - public ProjectileSpawns( - Direction dir, - int x, - int y, - int z, - Guid mapId, - AnimationBase animBase, - bool autoRotate, - ProjectileBase projectileBase, - Entity parent - ) - { - X = x; - Y = y; - SpawnX = X; - SpawnY = Y; - Z = z; - MapId = mapId; - SpawnMapId = MapId; - Dir = dir; - Anim = new Animation(animBase, true, autoRotate, Z, parent); - AutoRotate = autoRotate; - ProjectileBase = projectileBase; - TransmissionTimer = Timing.Global.Milliseconds + (ProjectileBase.Speed / ProjectileBase.Range); - } + public int Z; - public void Dispose() - { - Anim.DisposeNextDraw(); - } + public ProjectileSpawns( + Direction dir, + int x, + int y, + int z, + Guid mapId, + AnimationBase animBase, + bool autoRotate, + ProjectileBase projectileBase, + Entity parent + ) + { + X = x; + Y = y; + SpawnX = X; + SpawnY = Y; + Z = z; + MapId = mapId; + SpawnMapId = MapId; + Dir = dir; + Anim = new Animation(animBase, true, autoRotate, Z, parent); + AutoRotate = autoRotate; + ProjectileBase = projectileBase; + TransmissionTimer = Timing.Global.Milliseconds + (ProjectileBase.Speed / ProjectileBase.Range); + } + public void Dispose() + { + Anim.DisposeNextDraw(); } } diff --git a/Intersect.Client/Entities/Resource.cs b/Intersect.Client/Entities/Resource.cs index 627b07ca4c..7a9fe3fa6e 100644 --- a/Intersect.Client/Entities/Resource.cs +++ b/Intersect.Client/Entities/Resource.cs @@ -8,289 +8,287 @@ using Intersect.GameObjects; using Intersect.Network.Packets.Server; -namespace Intersect.Client.Entities -{ +namespace Intersect.Client.Entities; - public partial class Resource : Entity, IResource - { - private bool _waitingForTilesets; +public partial class Resource : Entity, IResource +{ - public ResourceBase BaseResource { get; set; } + private bool _waitingForTilesets; - bool IResource.IsDepleted => IsDead; + public ResourceBase BaseResource { get; set; } - public bool IsDead { get; set; } + bool IResource.IsDepleted => IsDead; - FloatRect mDestRectangle = FloatRect.Empty; + public bool IsDead { get; set; } - private bool mHasRenderBounds; + FloatRect mDestRectangle = FloatRect.Empty; - FloatRect mSrcRectangle = FloatRect.Empty; + private bool mHasRenderBounds; - public Resource(Guid id, ResourceEntityPacket packet) : base(id, packet, EntityType.Resource) - { - mRenderPriority = 0; - } + FloatRect mSrcRectangle = FloatRect.Empty; - public override string Sprite + public Resource(Guid id, ResourceEntityPacket packet) : base(id, packet, EntityType.Resource) + { + mRenderPriority = 0; + } + + public override string Sprite + { + get => mMySprite; + set { - get => mMySprite; - set + if (BaseResource == null) { - if (BaseResource == null) - { - return; - } + return; + } - mMySprite = value; - if (IsDead && BaseResource.Exhausted.GraphicFromTileset || - !IsDead && BaseResource.Initial.GraphicFromTileset) + mMySprite = value; + if (IsDead && BaseResource.Exhausted.GraphicFromTileset || + !IsDead && BaseResource.Initial.GraphicFromTileset) + { + if (GameContentManager.Current.TilesetsLoaded) { - if (GameContentManager.Current.TilesetsLoaded) - { - Texture = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Tileset, mMySprite); - } - else - { - _waitingForTilesets = true; - } + Texture = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Tileset, mMySprite); } else { - Texture = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Resource, mMySprite); + _waitingForTilesets = true; } - - mHasRenderBounds = false; - } - } - - public override void Load(EntityPacket packet) - { - base.Load(packet); - var pkt = (ResourceEntityPacket) packet; - IsDead = pkt.IsDead; - var baseId = pkt.ResourceId; - BaseResource = ResourceBase.Get(baseId); - HideName = true; - if (IsDead) - { - Sprite = BaseResource?.Exhausted.Graphic; } else { - Sprite = BaseResource?.Initial.Graphic; + Texture = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Resource, mMySprite); } + + mHasRenderBounds = false; } + } - public override void Dispose() + public override void Load(EntityPacket packet) + { + base.Load(packet); + var pkt = (ResourceEntityPacket) packet; + IsDead = pkt.IsDead; + var baseId = pkt.ResourceId; + BaseResource = ResourceBase.Get(baseId); + HideName = true; + if (IsDead) { - if (RenderList != null) - { - RenderList.Remove(this); - RenderList = null; - } + Sprite = BaseResource?.Exhausted.Graphic; + } + else + { + Sprite = BaseResource?.Initial.Graphic; + } + } - ClearAnimations(null); - mDisposed = true; + public override void Dispose() + { + if (RenderList != null) + { + RenderList.Remove(this); + RenderList = null; } - public override bool Update() + ClearAnimations(null); + mDisposed = true; + } + + public override bool Update() + { + if (mDisposed) { - if (mDisposed) + LatestMap = null; + + return false; + } + else + { + var map = Maps.MapInstance.Get(MapId); + LatestMap = map; + if (map == null || !map.InView()) { - LatestMap = null; + Globals.EntitiesToDispose.Add(Id); return false; } - else - { - var map = Maps.MapInstance.Get(MapId); - LatestMap = map; - if (map == null || !map.InView()) - { - Globals.EntitiesToDispose.Add(Id); + } - return false; - } - } + if (!mHasRenderBounds) + { + CalculateRenderBounds(); + } - if (!mHasRenderBounds) + if (!Graphics.WorldViewport.IntersectsWith(mDestRectangle)) + { + if (RenderList != null) { - CalculateRenderBounds(); + RenderList.Remove(this); } - if (!Graphics.WorldViewport.IntersectsWith(mDestRectangle)) - { - if (RenderList != null) - { - RenderList.Remove(this); - } - - return true; - } + return true; + } - var result = base.Update(); - if (!result) + var result = base.Update(); + if (!result) + { + if (RenderList != null) { - if (RenderList != null) - { - RenderList.Remove(this); - } + RenderList.Remove(this); } - - return result; } - /// - public override bool CanBeAttacked => !IsDead; + return result; + } + + /// + public override bool CanBeAttacked => !IsDead; - public override HashSet DetermineRenderOrder(HashSet renderList, IMapInstance map) + public override HashSet DetermineRenderOrder(HashSet renderList, IMapInstance map) + { + if (IsDead && !BaseResource.Exhausted.RenderBelowEntities) { - if (IsDead && !BaseResource.Exhausted.RenderBelowEntities) - { - return base.DetermineRenderOrder(renderList, map); - } + return base.DetermineRenderOrder(renderList, map); + } - if (!IsDead && !BaseResource.Initial.RenderBelowEntities) - { - return base.DetermineRenderOrder(renderList, map); - } + if (!IsDead && !BaseResource.Initial.RenderBelowEntities) + { + return base.DetermineRenderOrder(renderList, map); + } - //Otherwise we are alive or dead and we want to render below players/npcs - if (renderList != null) - { - renderList.Remove(this); - } + //Otherwise we are alive or dead and we want to render below players/npcs + if (renderList != null) + { + renderList.Remove(this); + } - if (map == null || Globals.Me == null || Globals.Me.MapInstance == null) - { - return null; - } + if (map == null || Globals.Me == null || Globals.Me.MapInstance == null) + { + return null; + } - var gridX = Globals.Me.MapInstance.GridX; - var gridY = Globals.Me.MapInstance.GridY; - for (var x = gridX - 1; x <= gridX + 1; x++) + var gridX = Globals.Me.MapInstance.GridX; + var gridY = Globals.Me.MapInstance.GridY; + for (var x = gridX - 1; x <= gridX + 1; x++) + { + for (var y = gridY - 1; y <= gridY + 1; y++) { - for (var y = gridY - 1; y <= gridY + 1; y++) + if (x >= 0 && + x < Globals.MapGridWidth && + y >= 0 && + y < Globals.MapGridHeight && + Globals.MapGrid[x, y] != Guid.Empty) { - if (x >= 0 && - x < Globals.MapGridWidth && - y >= 0 && - y < Globals.MapGridHeight && - Globals.MapGrid[x, y] != Guid.Empty) + if (Globals.MapGrid[x, y] == MapId) { - if (Globals.MapGrid[x, y] == MapId) + var priority = mRenderPriority; + if (Z != 0) { - var priority = mRenderPriority; - if (Z != 0) - { - priority += 3; - } - - HashSet renderSet; - - if (y == gridY - 1) - { - renderSet = Graphics.RenderingEntities[priority, Y]; - } - else if (y == gridY) - { - renderSet = Graphics.RenderingEntities[priority, Options.MapHeight + Y]; - } - else - { - renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * 2 + Y]; - } - - renderSet.Add(this); - renderList = renderSet; - - return renderList; + priority += 3; + } + HashSet renderSet; + + if (y == gridY - 1) + { + renderSet = Graphics.RenderingEntities[priority, Y]; } + else if (y == gridY) + { + renderSet = Graphics.RenderingEntities[priority, Options.MapHeight + Y]; + } + else + { + renderSet = Graphics.RenderingEntities[priority, Options.MapHeight * 2 + Y]; + } + + renderSet.Add(this); + renderList = renderSet; + + return renderList; + } } } + } + + return renderList; + } - return renderList; + private void CalculateRenderBounds() + { + var map = MapInstance; + if (map == null) + { + return; } - private void CalculateRenderBounds() + if (_waitingForTilesets && !GameContentManager.Current.TilesetsLoaded) { - var map = MapInstance; - if (map == null) - { - return; - } + return; + } - if (_waitingForTilesets && !GameContentManager.Current.TilesetsLoaded) + if (_waitingForTilesets && GameContentManager.Current.TilesetsLoaded) + { + _waitingForTilesets = false; + Sprite = Sprite; + } + + if (Texture != null) + { + mSrcRectangle.X = 0; + mSrcRectangle.Y = 0; + if (IsDead && BaseResource.Exhausted.GraphicFromTileset) { - return; + mSrcRectangle.X = BaseResource.Exhausted.X * Options.TileWidth; + mSrcRectangle.Y = BaseResource.Exhausted.Y * Options.TileHeight; + mSrcRectangle.Width = (BaseResource.Exhausted.Width + 1) * Options.TileWidth; + mSrcRectangle.Height = (BaseResource.Exhausted.Height + 1) * Options.TileHeight; } - - if (_waitingForTilesets && GameContentManager.Current.TilesetsLoaded) + else if (!IsDead && BaseResource.Initial.GraphicFromTileset) { - _waitingForTilesets = false; - Sprite = Sprite; + mSrcRectangle.X = BaseResource.Initial.X * Options.TileWidth; + mSrcRectangle.Y = BaseResource.Initial.Y * Options.TileHeight; + mSrcRectangle.Width = (BaseResource.Initial.Width + 1) * Options.TileWidth; + mSrcRectangle.Height = (BaseResource.Initial.Height + 1) * Options.TileHeight; } - - if (Texture != null) + else { - mSrcRectangle.X = 0; - mSrcRectangle.Y = 0; - if (IsDead && BaseResource.Exhausted.GraphicFromTileset) - { - mSrcRectangle.X = BaseResource.Exhausted.X * Options.TileWidth; - mSrcRectangle.Y = BaseResource.Exhausted.Y * Options.TileHeight; - mSrcRectangle.Width = (BaseResource.Exhausted.Width + 1) * Options.TileWidth; - mSrcRectangle.Height = (BaseResource.Exhausted.Height + 1) * Options.TileHeight; - } - else if (!IsDead && BaseResource.Initial.GraphicFromTileset) - { - mSrcRectangle.X = BaseResource.Initial.X * Options.TileWidth; - mSrcRectangle.Y = BaseResource.Initial.Y * Options.TileHeight; - mSrcRectangle.Width = (BaseResource.Initial.Width + 1) * Options.TileWidth; - mSrcRectangle.Height = (BaseResource.Initial.Height + 1) * Options.TileHeight; - } - else - { - mSrcRectangle.Width = Texture.GetWidth(); - mSrcRectangle.Height = Texture.GetHeight(); - } - - mDestRectangle.Width = mSrcRectangle.Width; - mDestRectangle.Height = mSrcRectangle.Height; - mDestRectangle.Y = (int) (map.Y + Y * Options.TileHeight + OffsetY); - mDestRectangle.X = (int) (map.X + X * Options.TileWidth + OffsetX); - if (mSrcRectangle.Height > Options.TileHeight) - { - mDestRectangle.Y -= mSrcRectangle.Height - Options.TileHeight; - } - - if (mSrcRectangle.Width > Options.TileWidth) - { - mDestRectangle.X -= (mSrcRectangle.Width - Options.TileWidth) / 2; - } - - mHasRenderBounds = true; + mSrcRectangle.Width = Texture.GetWidth(); + mSrcRectangle.Height = Texture.GetHeight(); } - } - //Rendering Resources - public override void Draw() - { - if (MapInstance == null) + mDestRectangle.Width = mSrcRectangle.Width; + mDestRectangle.Height = mSrcRectangle.Height; + mDestRectangle.Y = (int) (map.Y + Y * Options.TileHeight + OffsetY); + mDestRectangle.X = (int) (map.X + X * Options.TileWidth + OffsetX); + if (mSrcRectangle.Height > Options.TileHeight) { - return; + mDestRectangle.Y -= mSrcRectangle.Height - Options.TileHeight; } - if (Texture != null) + if (mSrcRectangle.Width > Options.TileWidth) { - Graphics.DrawGameTexture(Texture, mSrcRectangle, mDestRectangle, Intersect.Color.White); + mDestRectangle.X -= (mSrcRectangle.Width - Options.TileWidth) / 2; } + + mHasRenderBounds = true; + } + } + + //Rendering Resources + public override void Draw() + { + if (MapInstance == null) + { + return; } + if (Texture != null) + { + Graphics.DrawGameTexture(Texture, mSrcRectangle, mDestRectangle, Intersect.Color.White); + } } } diff --git a/Intersect.Client/Entities/Status.cs b/Intersect.Client/Entities/Status.cs index 9bd72f3df7..2a6597d825 100644 --- a/Intersect.Client/Entities/Status.cs +++ b/Intersect.Client/Entities/Status.cs @@ -2,40 +2,38 @@ using Intersect.Enums; using Intersect.Utilities; -namespace Intersect.Client.Entities -{ +namespace Intersect.Client.Entities; - public partial class Status : IStatus - { - public string Data { get; set; } = ""; +public partial class Status : IStatus +{ - public long[] Shield { get; set; } = new long[Enum.GetValues().Length]; + public string Data { get; set; } = ""; - public Guid SpellId { get; set; } + public long[] Shield { get; set; } = new long[Enum.GetValues().Length]; - public long TimeRecevied { get; set; } = 0; + public Guid SpellId { get; set; } - public long TimeRemaining { get; set; } = 0; + public long TimeRecevied { get; set; } = 0; - public long TotalDuration { get; set; } = 1; + public long TimeRemaining { get; set; } = 0; - public SpellEffect Type { get; set; } + public long TotalDuration { get; set; } = 1; - public Status(Guid spellId, SpellEffect type, string data, long timeRemaining, long totalDuration) - { - SpellId = spellId; - Type = type; - Data = data; - TimeRemaining = timeRemaining; - TotalDuration = totalDuration; - TimeRecevied = Timing.Global.Milliseconds; - } + public SpellEffect Type { get; set; } - public bool IsActive => RemainingMs > 0; + public Status(Guid spellId, SpellEffect type, string data, long timeRemaining, long totalDuration) + { + SpellId = spellId; + Type = type; + Data = data; + TimeRemaining = timeRemaining; + TotalDuration = totalDuration; + TimeRecevied = Timing.Global.Milliseconds; + } - public long RemainingMs => TimeRemaining - (Timing.Global.Milliseconds - TimeRecevied); + public bool IsActive => RemainingMs > 0; - } + public long RemainingMs => TimeRemaining - (Timing.Global.Milliseconds - TimeRecevied); } diff --git a/Intersect.Client/General/Globals.cs b/Intersect.Client/General/Globals.cs index 52df1ec7af..bd69fea615 100644 --- a/Intersect.Client/General/Globals.cs +++ b/Intersect.Client/General/Globals.cs @@ -13,232 +13,230 @@ using Intersect.GameObjects; using Intersect.Network.Packets.Server; -namespace Intersect.Client.General +namespace Intersect.Client.General; + + +public static partial class Globals { - public static partial class Globals - { + //Only need 1 table, and that is the one we see at a given moment in time. + public static CraftingTableBase ActiveCraftingTable; - //Only need 1 table, and that is the one we see at a given moment in time. - public static CraftingTableBase ActiveCraftingTable; + public static int AnimFrame = 0; - public static int AnimFrame = 0; + //Bag + public static Item[] Bag = null; - //Bag - public static Item[] Bag = null; + //Bank + public static Item[] Bank; + public static bool GuildBank; + public static int BankSlots; - //Bank - public static Item[] Bank; - public static bool GuildBank; - public static int BankSlots; + public static bool ConnectionLost; - public static bool ConnectionLost; + /// + /// This is used to prevent the client from showing unnecessary disconnect messages + /// + public static bool SoftLogout; - /// - /// This is used to prevent the client from showing unnecessary disconnect messages - /// - public static bool SoftLogout; + //Game Systems + public static GameContentManager ContentManager; - //Game Systems - public static GameContentManager ContentManager; + public static int CurrentMap = -1; - public static int CurrentMap = -1; + public static GameDatabase Database; - public static GameDatabase Database; + //Entities and stuff + //public static List Entities = new List(); + public static Dictionary Entities = new Dictionary(); - //Entities and stuff - //public static List Entities = new List(); - public static Dictionary Entities = new Dictionary(); + public static List EntitiesToDispose = new List(); - public static List EntitiesToDispose = new List(); + //Control Objects + public static List EventDialogs = new List(); - //Control Objects - public static List EventDialogs = new List(); + public static Dictionary EventHolds = new Dictionary(); - public static Dictionary EventHolds = new Dictionary(); + //Game Lock + public static object GameLock = new object(); - //Game Lock - public static object GameLock = new object(); + //Game Shop + //Only need 1 shop, and that is the one we see at a given moment in time. + public static ShopBase GameShop; - //Game Shop - //Only need 1 shop, and that is the one we see at a given moment in time. - public static ShopBase GameShop; + //Crucial game variables - //Crucial game variables + internal static List ClientLifecycleHelpers { get; } = + new List(); - internal static List ClientLifecycleHelpers { get; } = - new List(); + internal static void OnLifecycleChangeState() + { + ClientLifecycleHelpers.ForEach( + clientLifecycleHelper => clientLifecycleHelper?.OnLifecycleChangeState(GameState) + ); + } - internal static void OnLifecycleChangeState() - { - ClientLifecycleHelpers.ForEach( - clientLifecycleHelper => clientLifecycleHelper?.OnLifecycleChangeState(GameState) - ); - } + internal static void OnGameUpdate(TimeSpan deltaTime) + { + // Gather all known entities before passing them on to the plugins! + // The global entity list is incomplete and lacks events. + var knownEntities = new Dictionary(); - internal static void OnGameUpdate(TimeSpan deltaTime) + if (Entities != null) { - // Gather all known entities before passing them on to the plugins! - // The global entity list is incomplete and lacks events. - var knownEntities = new Dictionary(); - - if (Entities != null) + foreach (var en in Entities) { - foreach (var en in Entities) + if (!knownEntities.ContainsKey(en.Key)) { - if (!knownEntities.ContainsKey(en.Key)) - { - knownEntities.Add(en.Key, en.Value); - } + knownEntities.Add(en.Key, en.Value); } } - - if (MapGrid != null) + } + + if (MapGrid != null) + { + for (var x = 0; x < MapGridWidth; x++) { - for (var x = 0; x < MapGridWidth; x++) + for (var y = 0; y < MapGridHeight; y++) { - for (var y = 0; y < MapGridHeight; y++) + var map = MapInstance.Get(MapGrid[x, y]); + if (map != null) { - var map = MapInstance.Get(MapGrid[x, y]); - if (map != null) + foreach (var en in map.LocalEntities) { - foreach (var en in map.LocalEntities) + if (!knownEntities.ContainsKey(en.Key)) { - if (!knownEntities.ContainsKey(en.Key)) - { - knownEntities.Add(en.Key, en.Value); - } + knownEntities.Add(en.Key, en.Value); } } } } } - - ClientLifecycleHelpers.ForEach( - clientLifecycleHelper => clientLifecycleHelper?.OnGameUpdate(GameState, Globals.Me, knownEntities, deltaTime) - ); } + + ClientLifecycleHelpers.ForEach( + clientLifecycleHelper => clientLifecycleHelper?.OnGameUpdate(GameState, Globals.Me, knownEntities, deltaTime) + ); + } - internal static void OnGameDraw(DrawStates state, TimeSpan deltaTime) - { - ClientLifecycleHelpers.ForEach( - clientLifecycleHelper => clientLifecycleHelper?.OnGameDraw(state, deltaTime) - ); - } + internal static void OnGameDraw(DrawStates state, TimeSpan deltaTime) + { + ClientLifecycleHelpers.ForEach( + clientLifecycleHelper => clientLifecycleHelper?.OnGameDraw(state, deltaTime) + ); + } - internal static void OnGameDraw(DrawStates state, IEntity entity, TimeSpan deltaTime) - { - ClientLifecycleHelpers.ForEach( - clientLifecycleHelper => clientLifecycleHelper?.OnGameDraw(state, entity, deltaTime) - ); - } + internal static void OnGameDraw(DrawStates state, IEntity entity, TimeSpan deltaTime) + { + ClientLifecycleHelpers.ForEach( + clientLifecycleHelper => clientLifecycleHelper?.OnGameDraw(state, entity, deltaTime) + ); + } - private static GameStates mGameState = GameStates.Intro; + private static GameStates mGameState = GameStates.Intro; - /// - public static GameStates GameState + /// + public static GameStates GameState + { + get => mGameState; + set { - get => mGameState; - set - { - mGameState = value; - OnLifecycleChangeState(); - } + mGameState = value; + OnLifecycleChangeState(); } + } - public static List GridMaps = new List(); + public static List GridMaps = new List(); - public static bool HasGameData = false; + public static bool HasGameData = false; - public static bool InBag = false; + public static bool InBag = false; - public static bool InBank = false; + public static bool InBank = false; - //Crafting station - public static bool InCraft = false; + //Crafting station + public static bool InCraft = false; - public static bool InShop => GameShop != null; + public static bool InShop => GameShop != null; - public static bool InTrade = false; + public static bool InTrade = false; - public static bool CanCloseInventory => !(InBag || InBank || InCraft || InShop || InTrade); + public static bool CanCloseInventory => !(InBag || InBank || InCraft || InShop || InTrade); - public static GameInput InputManager; + public static GameInput InputManager; - public static bool IntroComing = true; + public static bool IntroComing = true; - public static long IntroDelay = 2000; + public static long IntroDelay = 2000; - //Engine Progression - public static int IntroIndex = 0; + //Engine Progression + public static int IntroIndex = 0; - public static long IntroStartTime = -1; + public static long IntroStartTime = -1; - public static bool IsRunning = true; + public static bool IsRunning = true; - public static bool JoiningGame = false; + public static bool JoiningGame = false; - public static bool LoggedIn = false; + public static bool LoggedIn = false; - //Map/Chunk Array - public static Guid[,] MapGrid; + //Map/Chunk Array + public static Guid[,] MapGrid; - public static long MapGridHeight; + public static long MapGridHeight; - public static long MapGridWidth; + public static long MapGridWidth; - //Local player information - public static Player Me; + //Local player information + public static Player Me; - public static bool MoveRouteActive = false; + public static bool MoveRouteActive = false; - public static bool NeedsMaps = true; + public static bool NeedsMaps = true; - //Event Guid and the Map its associated with - public static Dictionary> PendingEvents = - new Dictionary>(); + //Event Guid and the Map its associated with + public static Dictionary> PendingEvents = + new Dictionary>(); - //Event Show Pictures - public static ShowPicturePacket Picture; + //Event Show Pictures + public static ShowPicturePacket Picture; - public static List QuestOffers = new List(); + public static List QuestOffers = new List(); - public static Random Random = new Random(); + public static Random Random = new Random(); - public static GameSystem System; + public static GameSystem System; - //Trading (Only 2 people can trade at once) - public static Item[,] Trade; + //Trading (Only 2 people can trade at once) + public static Item[,] Trade; - //Scene management - private static bool _waitingOnServer; + //Scene management + private static bool _waitingOnServer; - public static bool WaitingOnServer - { - get => _waitingOnServer; - set => _waitingOnServer = value; - } + public static bool WaitingOnServer + { + get => _waitingOnServer; + set => _waitingOnServer = value; + } - public static Entity GetEntity(Guid id, EntityType type) + public static Entity GetEntity(Guid id, EntityType type) + { + if (Entities.ContainsKey(id)) { - if (Entities.ContainsKey(id)) - { - var entity = Entities[id]; + var entity = Entities[id]; - if (!entity.IsDisposed() && entity.Type == type) - { - EntitiesToDispose.Remove(entity.Id); - - return entity; - } + if (!entity.IsDisposed() && entity.Type == type) + { + EntitiesToDispose.Remove(entity.Id); - entity.Dispose(); - Entities.Remove(id); + return entity; } - return default; + entity.Dispose(); + Entities.Remove(id); } + return default; } } diff --git a/Intersect.Client/General/Time.cs b/Intersect.Client/General/Time.cs index c29511fcf0..c78835e66d 100644 --- a/Intersect.Client/General/Time.cs +++ b/Intersect.Client/General/Time.cs @@ -1,89 +1,87 @@ using Intersect.Utilities; -namespace Intersect.Client.General +namespace Intersect.Client.General; + + +public static partial class Time { - public static partial class Time - { + private static long sColorUpdate; - private static long sColorUpdate; + private static ColorF sCurrentColor = ColorF.White; - private static ColorF sCurrentColor = ColorF.White; + private static float sRate = 1f; - private static float sRate = 1f; + private static DateTime sServerTime = DateTime.Now; - private static DateTime sServerTime = DateTime.Now; + private static Color sTargetColor = Color.Transparent; - private static Color sTargetColor = Color.Transparent; + private static long sUpdateTime; - private static long sUpdateTime; + public static void LoadTime(DateTime timeUpdate, Color clr, float rate) + { + sServerTime = timeUpdate; + sTargetColor = clr; + sUpdateTime = 0; + sRate = rate; + } - public static void LoadTime(DateTime timeUpdate, Color clr, float rate) + public static void Update() + { + if (sUpdateTime < Timing.Global.Milliseconds) { - sServerTime = timeUpdate; - sTargetColor = clr; - sUpdateTime = 0; - sRate = rate; + var ts = new TimeSpan(0, 0, 0, 0, (int) (1000 * sRate)); + sServerTime = sServerTime.Add(ts); + sUpdateTime = Timing.Global.Milliseconds + 1000; } - public static void Update() + float ecTime = Timing.Global.MillisecondsUtc - sColorUpdate; + var valChange = 255 * ecTime / 10000f; + sCurrentColor.A = LerpVal(sCurrentColor.A, sTargetColor.A, valChange); + sCurrentColor.R = LerpVal(sCurrentColor.R, sTargetColor.R, valChange); + sCurrentColor.G = LerpVal(sCurrentColor.G, sTargetColor.G, valChange); + sCurrentColor.B = LerpVal(sCurrentColor.B, sTargetColor.B, valChange); + + sColorUpdate = Timing.Global.MillisecondsUtc; + } + + private static float LerpVal(float val, float target, float amt) + { + if (val < target) { - if (sUpdateTime < Timing.Global.Milliseconds) + if (val + amt > target) { - var ts = new TimeSpan(0, 0, 0, 0, (int) (1000 * sRate)); - sServerTime = sServerTime.Add(ts); - sUpdateTime = Timing.Global.Milliseconds + 1000; + val = target; + } + else + { + val += amt; } - - float ecTime = Timing.Global.MillisecondsUtc - sColorUpdate; - var valChange = 255 * ecTime / 10000f; - sCurrentColor.A = LerpVal(sCurrentColor.A, sTargetColor.A, valChange); - sCurrentColor.R = LerpVal(sCurrentColor.R, sTargetColor.R, valChange); - sCurrentColor.G = LerpVal(sCurrentColor.G, sTargetColor.G, valChange); - sCurrentColor.B = LerpVal(sCurrentColor.B, sTargetColor.B, valChange); - - sColorUpdate = Timing.Global.MillisecondsUtc; } - private static float LerpVal(float val, float target, float amt) + if (val > target) { - if (val < target) + if (val - amt < target) { - if (val + amt > target) - { - val = target; - } - else - { - val += amt; - } + val = target; } - - if (val > target) + else { - if (val - amt < target) - { - val = target; - } - else - { - val -= amt; - } + val -= amt; } - - return val; } - public static string GetTime() - { - return sServerTime.ToString("h:mm:ss tt"); - } + return val; + } - public static ColorF GetTintColor() - { - return sCurrentColor; - } + public static string GetTime() + { + return sServerTime.ToString("h:mm:ss tt"); + } + public static ColorF GetTintColor() + { + return sCurrentColor; } } diff --git a/Intersect.Client/Interface/Debugging/DebugWindow.cs b/Intersect.Client/Interface/Debugging/DebugWindow.cs index 931ba3896e..3c9d3351bd 100644 --- a/Intersect.Client/Interface/Debugging/DebugWindow.cs +++ b/Intersect.Client/Interface/Debugging/DebugWindow.cs @@ -10,282 +10,281 @@ using static Intersect.Client.Framework.File_Management.GameContentManager; -namespace Intersect.Client.Interface.Debugging +namespace Intersect.Client.Interface.Debugging; + +internal sealed partial class DebugWindow : Window { - internal sealed partial class DebugWindow : Window + private readonly List _disposables; + private bool _wasParentDrawDebugOutlinesEnabled; + private bool _drawDebugOutlinesEnabled; + + public DebugWindow(Base parent) : base(parent, Strings.Debug.Title, false, nameof(DebugWindow)) { - private readonly List _disposables; - private bool _wasParentDrawDebugOutlinesEnabled; - private bool _drawDebugOutlinesEnabled; + _disposables = new List(); - public DebugWindow(Base parent) : base(parent, Strings.Debug.Title, false, nameof(DebugWindow)) - { - _disposables = new List(); + DisableResizing(); - DisableResizing(); + IsHidden = true; + } - IsHidden = true; - } + private LabeledCheckBox CheckboxDrawDebugOutlines { get; set; } - private LabeledCheckBox CheckboxDrawDebugOutlines { get; set; } + private LabeledCheckBox CheckboxEnableLayoutHotReloading { get; set; } - private LabeledCheckBox CheckboxEnableLayoutHotReloading { get; set; } + private Button ButtonShutdownServer { get; set; } - private Button ButtonShutdownServer { get; set; } + private Button ButtonShutdownServerAndExit { get; set; } - private Button ButtonShutdownServerAndExit { get; set; } + private Table TableDebugStats { get; set; } - private Table TableDebugStats { get; set; } + protected override void EnsureInitialized() + { + CheckboxDrawDebugOutlines = CreateCheckboxDrawDebugOutlines(); + CheckboxEnableLayoutHotReloading = CreateCheckboxEnableLayoutHotReloading(); + ButtonShutdownServer = CreateButtonShutdownServer(); + ButtonShutdownServerAndExit = CreateButtonShutdownServerAndExit(); + TableDebugStats = CreateTableDebugStats(); - protected override void EnsureInitialized() - { - CheckboxDrawDebugOutlines = CreateCheckboxDrawDebugOutlines(); - CheckboxEnableLayoutHotReloading = CreateCheckboxEnableLayoutHotReloading(); - ButtonShutdownServer = CreateButtonShutdownServer(); - ButtonShutdownServerAndExit = CreateButtonShutdownServerAndExit(); - TableDebugStats = CreateTableDebugStats(); + LoadJsonUi(UI.Debug, Graphics.Renderer.GetResolutionString()); + } - LoadJsonUi(UI.Debug, Graphics.Renderer.GetResolutionString()); - } + protected override void OnAttached(Base parent) + { + base.OnAttached(parent); - protected override void OnAttached(Base parent) - { - base.OnAttached(parent); + Root.DrawDebugOutlines = _drawDebugOutlinesEnabled; + } - Root.DrawDebugOutlines = _drawDebugOutlinesEnabled; - } + protected override void OnAttaching(Base newParent) + { + base.OnAttaching(newParent); + _wasParentDrawDebugOutlinesEnabled = newParent.DrawDebugOutlines; + } - protected override void OnAttaching(Base newParent) - { - base.OnAttaching(newParent); - _wasParentDrawDebugOutlinesEnabled = newParent.DrawDebugOutlines; - } + protected override void OnDetached() + { + base.OnDetached(); + } - protected override void OnDetached() + protected override void OnDetaching(Base oldParent) + { + base.OnDetaching(oldParent); + oldParent.DrawDebugOutlines = _wasParentDrawDebugOutlinesEnabled; + } + + public override void Dispose() + { + foreach (var disposable in _disposables) { - base.OnDetached(); + disposable?.Dispose(); } - protected override void OnDetaching(Base oldParent) + base.Dispose(); + } + + private LabeledCheckBox CreateCheckboxDrawDebugOutlines() + { + var checkbox = new LabeledCheckBox(this, nameof(CheckboxDrawDebugOutlines)) { - base.OnDetaching(oldParent); - oldParent.DrawDebugOutlines = _wasParentDrawDebugOutlinesEnabled; - } + IsChecked = Root?.DrawDebugOutlines ?? false, + Text = Strings.Debug.DrawDebugOutlines, + }; - public override void Dispose() + checkbox.CheckChanged += (sender, args) => { - foreach (var disposable in _disposables) + _drawDebugOutlinesEnabled = checkbox.IsChecked; + if (Root != default) { - disposable?.Dispose(); + Root.DrawDebugOutlines = _drawDebugOutlinesEnabled; } + }; - base.Dispose(); - } + return checkbox; + } - private LabeledCheckBox CreateCheckboxDrawDebugOutlines() + private LabeledCheckBox CreateCheckboxEnableLayoutHotReloading() + { + var checkbox = new LabeledCheckBox(this, nameof(CheckboxEnableLayoutHotReloading)) { - var checkbox = new LabeledCheckBox(this, nameof(CheckboxDrawDebugOutlines)) - { - IsChecked = Root?.DrawDebugOutlines ?? false, - Text = Strings.Debug.DrawDebugOutlines, - }; - - checkbox.CheckChanged += (sender, args) => - { - _drawDebugOutlinesEnabled = checkbox.IsChecked; - if (Root != default) - { - Root.DrawDebugOutlines = _drawDebugOutlinesEnabled; - } - }; - - return checkbox; - } + IsChecked = Globals.ContentManager.ContentWatcher.Enabled, + Text = Strings.Debug.EnableLayoutHotReloading, + }; - private LabeledCheckBox CreateCheckboxEnableLayoutHotReloading() + checkbox.CheckChanged += (sender, args) => { - var checkbox = new LabeledCheckBox(this, nameof(CheckboxEnableLayoutHotReloading)) - { - IsChecked = Globals.ContentManager.ContentWatcher.Enabled, - Text = Strings.Debug.EnableLayoutHotReloading, - }; - - checkbox.CheckChanged += (sender, args) => - { - Globals.ContentManager.ContentWatcher.Enabled = checkbox.IsChecked; - }; + Globals.ContentManager.ContentWatcher.Enabled = checkbox.IsChecked; + }; - checkbox.SetToolTipText(Strings.Internals.ExperimentalFeatureTooltip); - checkbox.ToolTipFont = Skin.DefaultFont; + checkbox.SetToolTipText(Strings.Internals.ExperimentalFeatureTooltip); + checkbox.ToolTipFont = Skin.DefaultFont; - return checkbox; - } + return checkbox; + } - private Button CreateButtonShutdownServer() + private Button CreateButtonShutdownServer() + { + var button = new Button(this, nameof(ButtonShutdownServer)) { - var button = new Button(this, nameof(ButtonShutdownServer)) - { - IsHidden = true, - Text = Strings.Debug.ShutdownServer, - }; + IsHidden = true, + Text = Strings.Debug.ShutdownServer, + }; - button.Clicked += (sender, args) => - { - // TODO: Implement - }; + button.Clicked += (sender, args) => + { + // TODO: Implement + }; - return button; - } + return button; + } - private Button CreateButtonShutdownServerAndExit() + private Button CreateButtonShutdownServerAndExit() + { + var button = new Button(this, nameof(ButtonShutdownServerAndExit)) { - var button = new Button(this, nameof(ButtonShutdownServerAndExit)) - { - IsHidden = true, - Text = Strings.Debug.ShutdownServerAndExit, - }; + IsHidden = true, + Text = Strings.Debug.ShutdownServerAndExit, + }; - button.Clicked += (sender, args) => - { - // TODO: Implement - }; + button.Clicked += (sender, args) => + { + // TODO: Implement + }; - return button; - } + return button; + } - private Table CreateTableDebugStats() + private Table CreateTableDebugStats() + { + var table = new Table(this, nameof(TableDebugStats)) { - var table = new Table(this, nameof(TableDebugStats)) - { - ColumnCount = 2, - }; + ColumnCount = 2, + }; - var fpsProvider = new ValueTableCellDataProvider(() => Graphics.Renderer.GetFps()); - table.AddRow(Strings.Debug.Fps).Listen(fpsProvider, 1); - _disposables.Add(fpsProvider.Generator.Start()); + var fpsProvider = new ValueTableCellDataProvider(() => Graphics.Renderer.GetFps()); + table.AddRow(Strings.Debug.Fps).Listen(fpsProvider, 1); + _disposables.Add(fpsProvider.Generator.Start()); - var pingProvider = new ValueTableCellDataProvider(() => Networking.Network.Ping); - table.AddRow(Strings.Debug.Ping).Listen(pingProvider, 1); - _disposables.Add(pingProvider.Generator.Start()); + var pingProvider = new ValueTableCellDataProvider(() => Networking.Network.Ping); + table.AddRow(Strings.Debug.Ping).Listen(pingProvider, 1); + _disposables.Add(pingProvider.Generator.Start()); - var drawCallsProvider = new ValueTableCellDataProvider(() => Graphics.DrawCalls); - table.AddRow(Strings.Debug.Draws).Listen(drawCallsProvider, 1); - _disposables.Add(drawCallsProvider.Generator.Start()); + var drawCallsProvider = new ValueTableCellDataProvider(() => Graphics.DrawCalls); + table.AddRow(Strings.Debug.Draws).Listen(drawCallsProvider, 1); + _disposables.Add(drawCallsProvider.Generator.Start()); - var mapNameProvider = new ValueTableCellDataProvider(() => - { - var mapId = Globals.Me?.MapId ?? default; - - if (mapId == default) - { - return Strings.Internals.NotApplicable; - } + var mapNameProvider = new ValueTableCellDataProvider(() => + { + var mapId = Globals.Me?.MapId ?? default; - return MapInstance.Get(mapId)?.Name ?? Strings.Internals.NotApplicable; - }); - table.AddRow(Strings.Debug.Map).Listen(mapNameProvider, 1); - _disposables.Add(mapNameProvider.Generator.Start()); + if (mapId == default) + { + return Strings.Internals.NotApplicable; + } - var coordinateXProvider = new ValueTableCellDataProvider(() => Globals.Me?.X ?? -1); - table.AddRow(Strings.Internals.CoordinateX).Listen(coordinateXProvider, 1); - _disposables.Add(coordinateXProvider.Generator.Start()); + return MapInstance.Get(mapId)?.Name ?? Strings.Internals.NotApplicable; + }); + table.AddRow(Strings.Debug.Map).Listen(mapNameProvider, 1); + _disposables.Add(mapNameProvider.Generator.Start()); - var coordinateYProvider = new ValueTableCellDataProvider(() => Globals.Me?.Y ?? -1); - table.AddRow(Strings.Internals.CoordinateY).Listen(coordinateYProvider, 1); - _disposables.Add(coordinateYProvider.Generator.Start()); + var coordinateXProvider = new ValueTableCellDataProvider(() => Globals.Me?.X ?? -1); + table.AddRow(Strings.Internals.CoordinateX).Listen(coordinateXProvider, 1); + _disposables.Add(coordinateXProvider.Generator.Start()); - var coordinateZProvider = new ValueTableCellDataProvider(() => Globals.Me?.Z ?? -1); - table.AddRow(Strings.Internals.CoordinateZ).Listen(coordinateZProvider, 1); - _disposables.Add(coordinateZProvider.Generator.Start()); + var coordinateYProvider = new ValueTableCellDataProvider(() => Globals.Me?.Y ?? -1); + table.AddRow(Strings.Internals.CoordinateY).Listen(coordinateYProvider, 1); + _disposables.Add(coordinateYProvider.Generator.Start()); - var knownEntitiesProvider = new ValueTableCellDataProvider(() => Graphics.DrawCalls); - table.AddRow(Strings.Debug.KnownEntities).Listen(knownEntitiesProvider, 1); - _disposables.Add(knownEntitiesProvider.Generator.Start()); + var coordinateZProvider = new ValueTableCellDataProvider(() => Globals.Me?.Z ?? -1); + table.AddRow(Strings.Internals.CoordinateZ).Listen(coordinateZProvider, 1); + _disposables.Add(coordinateZProvider.Generator.Start()); - var knownMapsProvider = new ValueTableCellDataProvider(() => MapInstance.Lookup.Count); - table.AddRow(Strings.Debug.KnownMaps).Listen(knownMapsProvider, 1); - _disposables.Add(knownMapsProvider.Generator.Start()); + var knownEntitiesProvider = new ValueTableCellDataProvider(() => Graphics.DrawCalls); + table.AddRow(Strings.Debug.KnownEntities).Listen(knownEntitiesProvider, 1); + _disposables.Add(knownEntitiesProvider.Generator.Start()); - var mapsDrawnProvider = new ValueTableCellDataProvider(() => Graphics.MapsDrawn); - table.AddRow(Strings.Debug.MapsDrawn).Listen(mapsDrawnProvider, 1); - _disposables.Add(mapsDrawnProvider.Generator.Start()); + var knownMapsProvider = new ValueTableCellDataProvider(() => MapInstance.Lookup.Count); + table.AddRow(Strings.Debug.KnownMaps).Listen(knownMapsProvider, 1); + _disposables.Add(knownMapsProvider.Generator.Start()); - var entitiesDrawnProvider = new ValueTableCellDataProvider(() => Graphics.EntitiesDrawn); - table.AddRow(Strings.Debug.EntitiesDrawn).Listen(entitiesDrawnProvider, 1); - _disposables.Add(entitiesDrawnProvider.Generator.Start()); + var mapsDrawnProvider = new ValueTableCellDataProvider(() => Graphics.MapsDrawn); + table.AddRow(Strings.Debug.MapsDrawn).Listen(mapsDrawnProvider, 1); + _disposables.Add(mapsDrawnProvider.Generator.Start()); - var lightsDrawnProvider = new ValueTableCellDataProvider(() => Graphics.LightsDrawn); - table.AddRow(Strings.Debug.LightsDrawn).Listen(lightsDrawnProvider, 1); - _disposables.Add(lightsDrawnProvider.Generator.Start()); + var entitiesDrawnProvider = new ValueTableCellDataProvider(() => Graphics.EntitiesDrawn); + table.AddRow(Strings.Debug.EntitiesDrawn).Listen(entitiesDrawnProvider, 1); + _disposables.Add(entitiesDrawnProvider.Generator.Start()); - var timeProvider = new ValueTableCellDataProvider(() => Time.GetTime()); - table.AddRow(Strings.Debug.Time).Listen(timeProvider, 1); - _disposables.Add(timeProvider.Generator.Start()); + var lightsDrawnProvider = new ValueTableCellDataProvider(() => Graphics.LightsDrawn); + table.AddRow(Strings.Debug.LightsDrawn).Listen(lightsDrawnProvider, 1); + _disposables.Add(lightsDrawnProvider.Generator.Start()); - var interfaceObjectsProvider = new ValueTableCellDataProvider((cancellationToken) => - { - try - { - return Interface.CurrentInterface?.Children.ToArray().SelectManyRecursive( - x => x.Children.ToArray(), - cancellationToken - ).ToArray().Length ?? 0; - } - catch (ObjectDisposedException) - { - throw; - } - catch (InvalidOperationException) - { - return 0; - } - }); - table.AddRow(Strings.Debug.InterfaceObjects).Listen(interfaceObjectsProvider, 1); - _disposables.Add(interfaceObjectsProvider.Generator.Start()); - - _ = table.AddRow(Strings.Debug.ControlUnderCursor, 1); - - var controlUnderCursorProvider = new ControlUnderCursorProvider(); - table.AddRow(Strings.Internals.Type).Listen(controlUnderCursorProvider, 0); - table.AddRow(Strings.Internals.Name).Listen(controlUnderCursorProvider, 1); - table.AddRow(Strings.Internals.LocalItem.ToString(Strings.Internals.Bounds)).Listen(controlUnderCursorProvider, 2); - table.AddRow(Strings.Internals.GlobalItem.ToString(Strings.Internals.Bounds)).Listen(controlUnderCursorProvider, 3); - table.AddRow(Strings.Internals.Color).Listen(controlUnderCursorProvider, 4); - table.AddRow(Strings.Internals.ColorOverride).Listen(controlUnderCursorProvider, 5); - _disposables.Add(controlUnderCursorProvider.Generator.Start()); - - return table; - } + var timeProvider = new ValueTableCellDataProvider(() => Time.GetTime()); + table.AddRow(Strings.Debug.Time).Listen(timeProvider, 1); + _disposables.Add(timeProvider.Generator.Start()); - private partial class ControlUnderCursorProvider : ITableDataProvider + var interfaceObjectsProvider = new ValueTableCellDataProvider((cancellationToken) => { - public ControlUnderCursorProvider() + try + { + return Interface.CurrentInterface?.Children.ToArray().SelectManyRecursive( + x => x.Children.ToArray(), + cancellationToken + ).ToArray().Length ?? 0; + } + catch (ObjectDisposedException) { - Generator = new CancellableGenerator(CreateControlUnderCursorGenerator); + throw; } + catch (InvalidOperationException) + { + return 0; + } + }); + table.AddRow(Strings.Debug.InterfaceObjects).Listen(interfaceObjectsProvider, 1); + _disposables.Add(interfaceObjectsProvider.Generator.Start()); + + _ = table.AddRow(Strings.Debug.ControlUnderCursor, 1); + + var controlUnderCursorProvider = new ControlUnderCursorProvider(); + table.AddRow(Strings.Internals.Type).Listen(controlUnderCursorProvider, 0); + table.AddRow(Strings.Internals.Name).Listen(controlUnderCursorProvider, 1); + table.AddRow(Strings.Internals.LocalItem.ToString(Strings.Internals.Bounds)).Listen(controlUnderCursorProvider, 2); + table.AddRow(Strings.Internals.GlobalItem.ToString(Strings.Internals.Bounds)).Listen(controlUnderCursorProvider, 3); + table.AddRow(Strings.Internals.Color).Listen(controlUnderCursorProvider, 4); + table.AddRow(Strings.Internals.ColorOverride).Listen(controlUnderCursorProvider, 5); + _disposables.Add(controlUnderCursorProvider.Generator.Start()); + + return table; + } + + private partial class ControlUnderCursorProvider : ITableDataProvider + { + public ControlUnderCursorProvider() + { + Generator = new CancellableGenerator(CreateControlUnderCursorGenerator); + } - public event TableDataChangedEventHandler DataChanged; + public event TableDataChangedEventHandler DataChanged; - public CancellableGenerator Generator { get; } + public CancellableGenerator Generator { get; } - public void Start() - { - _ = Generator.Start(); - } + public void Start() + { + _ = Generator.Start(); + } - private AsyncValueGenerator CreateControlUnderCursorGenerator(CancellationToken cancellationToken) + private AsyncValueGenerator CreateControlUnderCursorGenerator(CancellationToken cancellationToken) + { + return new AsyncValueGenerator(() => Task.Delay(100).ContinueWith((completedTask) => Interface.FindControlAtCursor(), TaskScheduler.Current), (component) => { - return new AsyncValueGenerator(() => Task.Delay(100).ContinueWith((completedTask) => Interface.FindControlAtCursor(), TaskScheduler.Current), (component) => - { - DataChanged?.Invoke(this, new TableDataChangedEventArgs(0, 1, default, component?.GetType().Name ?? Strings.Internals.NotApplicable)); - DataChanged?.Invoke(this, new TableDataChangedEventArgs(1, 1, default, component?.CanonicalName ?? string.Empty)); - DataChanged?.Invoke(this, new TableDataChangedEventArgs(2, 1, default, component?.Bounds.ToString() ?? string.Empty)); - DataChanged?.Invoke(this, new TableDataChangedEventArgs(3, 1, default, component?.BoundsGlobal.ToString() ?? string.Empty)); - DataChanged?.Invoke(this, new TableDataChangedEventArgs(4, 1, default, (component as IColorableText)?.TextColor ?? string.Empty)); - DataChanged?.Invoke(this, new TableDataChangedEventArgs(5, 1, default, (component as IColorableText)?.TextColorOverride ?? string.Empty)); - - }, cancellationToken); - } + DataChanged?.Invoke(this, new TableDataChangedEventArgs(0, 1, default, component?.GetType().Name ?? Strings.Internals.NotApplicable)); + DataChanged?.Invoke(this, new TableDataChangedEventArgs(1, 1, default, component?.CanonicalName ?? string.Empty)); + DataChanged?.Invoke(this, new TableDataChangedEventArgs(2, 1, default, component?.Bounds.ToString() ?? string.Empty)); + DataChanged?.Invoke(this, new TableDataChangedEventArgs(3, 1, default, component?.BoundsGlobal.ToString() ?? string.Empty)); + DataChanged?.Invoke(this, new TableDataChangedEventArgs(4, 1, default, (component as IColorableText)?.TextColor ?? string.Empty)); + DataChanged?.Invoke(this, new TableDataChangedEventArgs(5, 1, default, (component as IColorableText)?.TextColorOverride ?? string.Empty)); + + }, cancellationToken); } } } diff --git a/Intersect.Client/Interface/Game/AdminWindow.cs b/Intersect.Client/Interface/Game/AdminWindow.cs index 5f1a56f1f3..1e51b54ab1 100644 --- a/Intersect.Client/Interface/Game/AdminWindow.cs +++ b/Intersect.Client/Interface/Game/AdminWindow.cs @@ -9,445 +9,444 @@ using Intersect.GameObjects.Maps.MapList; using static Intersect.Client.Framework.File_Management.GameContentManager; -namespace Intersect.Client.Interface.Game -{ +namespace Intersect.Client.Interface.Game; - partial class AdminWindow - { - //Graphics - public ImagePanel PanelFace; - - public ImagePanel FacePanel; +partial class AdminWindow +{ - private ComboBox DropdownAccess; + //Graphics + public ImagePanel PanelFace; + + public ImagePanel FacePanel; - private Label LabelAccess; + private ComboBox DropdownAccess; - //Controls - private WindowControl mAdminWindow; + private Label LabelAccess; - private Button ButtonBan; + //Controls + private WindowControl mAdminWindow; - //Windows - BanMuteBox mBanMuteWindow; + private Button ButtonBan; - private CheckBox CheckboxChronological; + //Windows + BanMuteBox mBanMuteWindow; - private ComboBox DropdownFace; + private CheckBox CheckboxChronological; - private Label LabelFace; + private ComboBox DropdownFace; - //Player Mod Buttons - private Button ButtonKick; + private Label LabelFace; - private Button ButtonKill; + //Player Mod Buttons + private Button ButtonKick; - private Label LabelChronological; + private Button ButtonKill; - private TreeControl mMapList; + private Label LabelChronological; - private Label LabelMapList; + private TreeControl mMapList; - private Button ButtonMute; + private Label LabelMapList; - //Player Mod Labels - private Label LabelName; + private Button ButtonMute; - //Player Mod Textboxes - private TextBox TextboxName; + //Player Mod Labels + private Label LabelName; - private Button ButtonSetFace; + //Player Mod Textboxes + private TextBox TextboxName; - private Button ButtonSetPower; + private Button ButtonSetFace; - private Button ButtonSetSprite; + private Button ButtonSetPower; - private ComboBox DropdownSprite; + private Button ButtonSetSprite; - private Label LabelSprite; + private ComboBox DropdownSprite; - private Button ButtonUnban; + private Label LabelSprite; - private Button ButtonUnmute; + private Button ButtonUnban; - private Button ButtonWarpMeTo; + private Button ButtonUnmute; - private Button ButtonWarpToMe; - - private Button ButtonOverworldReturn; + private Button ButtonWarpMeTo; - public ImagePanel PanelSprite; + private Button ButtonWarpToMe; + + private Button ButtonOverworldReturn; - public ImagePanel SpritePanel; + public ImagePanel PanelSprite; - //Init - public AdminWindow(Base gameCanvas) + public ImagePanel SpritePanel; + + //Init + public AdminWindow(Base gameCanvas) + { + mAdminWindow = new WindowControl(gameCanvas, Strings.Admin.Title, false, nameof(AdminWindow)); + mAdminWindow.SetPosition( + (Graphics.Renderer.ScreenWidth - mAdminWindow.Width) / 2, + (Graphics.Renderer.ScreenHeight - mAdminWindow.Height) / 2 + ); + mAdminWindow.DisableResizing(); + mAdminWindow.Margin = Margin.Zero; + mAdminWindow.Padding = Padding.Zero; + + LabelName = new Label(mAdminWindow, nameof(LabelName)); + LabelName.Text = Strings.Admin.Name; + TextboxName = new TextBox(mAdminWindow, nameof(TextboxName)); + Interface.FocusElements.Add(TextboxName); + + LabelAccess = new Label(mAdminWindow, nameof(LabelAccess)); + LabelAccess.Text = Strings.Admin.Access; + DropdownAccess = new ComboBox(mAdminWindow, nameof(DropdownAccess)); + DropdownAccess.AddItem(Strings.Admin.Access0).UserData = "None"; + DropdownAccess.AddItem(Strings.Admin.Access1).UserData = "Moderator"; + DropdownAccess.AddItem(Strings.Admin.Access2).UserData = "Admin"; + ButtonSetPower = new Button(mAdminWindow, nameof(ButtonSetPower)) { Text = Strings.Admin.SetPower }; + ButtonSetPower.Clicked += _setPowerButton_Clicked; + + ButtonWarpToMe = new Button(mAdminWindow, nameof(ButtonWarpToMe)); + ButtonWarpToMe.Text = Strings.Admin.Warp2Me; + ButtonWarpToMe.Clicked += _warpToMeButton_Clicked; + + ButtonWarpMeTo = new Button(mAdminWindow, nameof(ButtonWarpMeTo)); + ButtonWarpMeTo.Text = Strings.Admin.WarpMe2; + ButtonWarpMeTo.Clicked += _warpMeToButton_Clicked; + + ButtonOverworldReturn = new Button(mAdminWindow, nameof(ButtonOverworldReturn)); + ButtonOverworldReturn.Text = Strings.Admin.OverworldReturn; + ButtonOverworldReturn.Clicked += _overWorldReturn_Clicked; + + ButtonKick = new Button(mAdminWindow, nameof(ButtonKick)); + ButtonKick.Text = Strings.Admin.Kick; + ButtonKick.Clicked += _kickButton_Clicked; + + ButtonKill = new Button(mAdminWindow, nameof(ButtonKill)); + ButtonKill.Text = Strings.Admin.Kill; + ButtonKill.Clicked += _killButton_Clicked; + + ButtonBan = new Button(mAdminWindow, nameof(ButtonBan)); + ButtonBan.Text = Strings.Admin.Ban; + ButtonBan.Clicked += _banButton_Clicked; + + ButtonUnban = new Button(mAdminWindow, nameof(ButtonUnban)); + ButtonUnban.Text = Strings.Admin.Unban; + ButtonUnban.Clicked += _unbanButton_Clicked; + + ButtonMute = new Button(mAdminWindow, nameof(ButtonMute)); + ButtonMute.Text = Strings.Admin.Mute; + ButtonMute.Clicked += _muteButton_Clicked; + + ButtonUnmute = new Button(mAdminWindow, nameof(ButtonUnmute)); + ButtonUnmute.Text = Strings.Admin.Unmute; + ButtonUnmute.Clicked += _unmuteButton_Clicked; + + LabelSprite = new Label(mAdminWindow, nameof(LabelSprite)); + LabelSprite.Text = Strings.Admin.Sprite; + DropdownSprite = new ComboBox(mAdminWindow, nameof(DropdownSprite)); + DropdownSprite.AddItem(Strings.Admin.None); + var sprites = Globals.ContentManager.GetTextureNames(Framework.Content.TextureType.Entity); + Array.Sort(sprites, new AlphanumComparatorFast()); + foreach (var sprite in sprites) { - mAdminWindow = new WindowControl(gameCanvas, Strings.Admin.Title, false, nameof(AdminWindow)); - mAdminWindow.SetPosition( - (Graphics.Renderer.ScreenWidth - mAdminWindow.Width) / 2, - (Graphics.Renderer.ScreenHeight - mAdminWindow.Height) / 2 - ); - mAdminWindow.DisableResizing(); - mAdminWindow.Margin = Margin.Zero; - mAdminWindow.Padding = Padding.Zero; - - LabelName = new Label(mAdminWindow, nameof(LabelName)); - LabelName.Text = Strings.Admin.Name; - TextboxName = new TextBox(mAdminWindow, nameof(TextboxName)); - Interface.FocusElements.Add(TextboxName); - - LabelAccess = new Label(mAdminWindow, nameof(LabelAccess)); - LabelAccess.Text = Strings.Admin.Access; - DropdownAccess = new ComboBox(mAdminWindow, nameof(DropdownAccess)); - DropdownAccess.AddItem(Strings.Admin.Access0).UserData = "None"; - DropdownAccess.AddItem(Strings.Admin.Access1).UserData = "Moderator"; - DropdownAccess.AddItem(Strings.Admin.Access2).UserData = "Admin"; - ButtonSetPower = new Button(mAdminWindow, nameof(ButtonSetPower)) { Text = Strings.Admin.SetPower }; - ButtonSetPower.Clicked += _setPowerButton_Clicked; - - ButtonWarpToMe = new Button(mAdminWindow, nameof(ButtonWarpToMe)); - ButtonWarpToMe.Text = Strings.Admin.Warp2Me; - ButtonWarpToMe.Clicked += _warpToMeButton_Clicked; - - ButtonWarpMeTo = new Button(mAdminWindow, nameof(ButtonWarpMeTo)); - ButtonWarpMeTo.Text = Strings.Admin.WarpMe2; - ButtonWarpMeTo.Clicked += _warpMeToButton_Clicked; - - ButtonOverworldReturn = new Button(mAdminWindow, nameof(ButtonOverworldReturn)); - ButtonOverworldReturn.Text = Strings.Admin.OverworldReturn; - ButtonOverworldReturn.Clicked += _overWorldReturn_Clicked; - - ButtonKick = new Button(mAdminWindow, nameof(ButtonKick)); - ButtonKick.Text = Strings.Admin.Kick; - ButtonKick.Clicked += _kickButton_Clicked; - - ButtonKill = new Button(mAdminWindow, nameof(ButtonKill)); - ButtonKill.Text = Strings.Admin.Kill; - ButtonKill.Clicked += _killButton_Clicked; - - ButtonBan = new Button(mAdminWindow, nameof(ButtonBan)); - ButtonBan.Text = Strings.Admin.Ban; - ButtonBan.Clicked += _banButton_Clicked; - - ButtonUnban = new Button(mAdminWindow, nameof(ButtonUnban)); - ButtonUnban.Text = Strings.Admin.Unban; - ButtonUnban.Clicked += _unbanButton_Clicked; - - ButtonMute = new Button(mAdminWindow, nameof(ButtonMute)); - ButtonMute.Text = Strings.Admin.Mute; - ButtonMute.Clicked += _muteButton_Clicked; - - ButtonUnmute = new Button(mAdminWindow, nameof(ButtonUnmute)); - ButtonUnmute.Text = Strings.Admin.Unmute; - ButtonUnmute.Clicked += _unmuteButton_Clicked; - - LabelSprite = new Label(mAdminWindow, nameof(LabelSprite)); - LabelSprite.Text = Strings.Admin.Sprite; - DropdownSprite = new ComboBox(mAdminWindow, nameof(DropdownSprite)); - DropdownSprite.AddItem(Strings.Admin.None); - var sprites = Globals.ContentManager.GetTextureNames(Framework.Content.TextureType.Entity); - Array.Sort(sprites, new AlphanumComparatorFast()); - foreach (var sprite in sprites) - { - DropdownSprite.AddItem(sprite); - } - DropdownSprite.ItemSelected += _spriteDropdown_ItemSelected; - ButtonSetSprite = new Button(mAdminWindow, nameof(ButtonSetSprite)); - ButtonSetSprite.Text = Strings.Admin.SetSprite; - ButtonSetSprite.Clicked += _setSpriteButton_Clicked; - PanelSprite = new ImagePanel(mAdminWindow, nameof(PanelSprite)); - SpritePanel = new ImagePanel(PanelSprite); - - LabelFace = new Label(mAdminWindow, nameof(LabelFace)); - LabelFace.Text = Strings.Admin.Face; - DropdownFace = new ComboBox(mAdminWindow, nameof(DropdownFace)); - DropdownFace.AddItem(Strings.Admin.None); - var faces = Globals.ContentManager.GetTextureNames(Framework.Content.TextureType.Face); - Array.Sort(faces, new AlphanumComparatorFast()); - foreach (var face in faces) - { - DropdownFace.AddItem(face); - } - DropdownFace.ItemSelected += _faceDropdown_ItemSelected; - ButtonSetFace = new Button(mAdminWindow, nameof(ButtonSetFace)); - ButtonSetFace.Text = Strings.Admin.SetFace; - ButtonSetFace.Clicked += _setFaceButton_Clicked; - PanelFace = new ImagePanel(mAdminWindow, nameof(PanelFace)); - FacePanel = new ImagePanel(PanelFace); - - LabelMapList = new Label(mAdminWindow, nameof(LabelMapList)) { Text = Strings.Admin.MapList }; - CheckboxChronological = new CheckBox(mAdminWindow, nameof(CheckboxChronological)); - CheckboxChronological.SetToolTipText(Strings.Admin.ChronologicalTip); - CheckboxChronological.CheckChanged += _chkChronological_CheckChanged; - LabelChronological = new Label(mAdminWindow, nameof(LabelChronological)) - { - Text = Strings.Admin.Chronological - }; - CreateMapList(); - mAdminWindow.LoadJsonUi(UI.InGame, Graphics.Renderer.GetResolutionString(), true); - UpdateMapList(); + DropdownSprite.AddItem(sprite); } - - private void _spriteDropdown_ItemSelected(Base sender, ItemSelectedEventArgs arguments) + DropdownSprite.ItemSelected += _spriteDropdown_ItemSelected; + ButtonSetSprite = new Button(mAdminWindow, nameof(ButtonSetSprite)); + ButtonSetSprite.Text = Strings.Admin.SetSprite; + ButtonSetSprite.Clicked += _setSpriteButton_Clicked; + PanelSprite = new ImagePanel(mAdminWindow, nameof(PanelSprite)); + SpritePanel = new ImagePanel(PanelSprite); + + LabelFace = new Label(mAdminWindow, nameof(LabelFace)); + LabelFace.Text = Strings.Admin.Face; + DropdownFace = new ComboBox(mAdminWindow, nameof(DropdownFace)); + DropdownFace.AddItem(Strings.Admin.None); + var faces = Globals.ContentManager.GetTextureNames(Framework.Content.TextureType.Face); + Array.Sort(faces, new AlphanumComparatorFast()); + foreach (var face in faces) { - SpritePanel.Texture = Globals.ContentManager.GetTexture( - Framework.Content.TextureType.Entity, DropdownSprite.Text); - - if (SpritePanel.Texture == null) - { - return; - } - - var textFrameWidth = SpritePanel.Texture.Width / Options.Instance.Sprites.NormalFrames; - var textFrameHeight = SpritePanel.Texture.Height / Options.Instance.Sprites.Directions; - SpritePanel.SetTextureRect(0, 0, textFrameWidth, textFrameHeight); - SpritePanel.SetSize(Math.Min(textFrameWidth, 46), Math.Min(textFrameHeight, 46)); - Align.Center(SpritePanel); + DropdownFace.AddItem(face); } - - private void _faceDropdown_ItemSelected(Base sender, ItemSelectedEventArgs arguments) + DropdownFace.ItemSelected += _faceDropdown_ItemSelected; + ButtonSetFace = new Button(mAdminWindow, nameof(ButtonSetFace)); + ButtonSetFace.Text = Strings.Admin.SetFace; + ButtonSetFace.Clicked += _setFaceButton_Clicked; + PanelFace = new ImagePanel(mAdminWindow, nameof(PanelFace)); + FacePanel = new ImagePanel(PanelFace); + + LabelMapList = new Label(mAdminWindow, nameof(LabelMapList)) { Text = Strings.Admin.MapList }; + CheckboxChronological = new CheckBox(mAdminWindow, nameof(CheckboxChronological)); + CheckboxChronological.SetToolTipText(Strings.Admin.ChronologicalTip); + CheckboxChronological.CheckChanged += _chkChronological_CheckChanged; + LabelChronological = new Label(mAdminWindow, nameof(LabelChronological)) { - FacePanel.Texture = Globals.ContentManager.GetTexture( - Framework.Content.TextureType.Face, DropdownFace.Text); - - if (FacePanel.Texture == null) - { - return; - } + Text = Strings.Admin.Chronological + }; + CreateMapList(); + mAdminWindow.LoadJsonUi(UI.InGame, Graphics.Renderer.GetResolutionString(), true); + UpdateMapList(); + } - var textFrameWidth = FacePanel.Texture.Width; - var textFrameHeight = FacePanel.Texture.Height; - FacePanel.SetTextureRect(0, 0, textFrameWidth, textFrameHeight); - FacePanel.SetSize(Math.Min(textFrameWidth, 46), Math.Min(textFrameHeight, 46)); - Align.Center(FacePanel); - } + private void _spriteDropdown_ItemSelected(Base sender, ItemSelectedEventArgs arguments) + { + SpritePanel.Texture = Globals.ContentManager.GetTexture( + Framework.Content.TextureType.Entity, DropdownSprite.Text); - //Methods - public void SetName(string name) + if (SpritePanel.Texture == null) { - TextboxName.Text = name; + return; } - private void CreateMapList() - { - mMapList = new TreeControl(mAdminWindow); - mMapList.SetPosition(4f, 330); - mMapList.Width = mAdminWindow.Width - 8; - mMapList.Height = 80; - mMapList.RenderColor = Color.FromArgb(255, 255, 255, 255); - mMapList.MaximumSize = new Point(4096, 999999); - } + var textFrameWidth = SpritePanel.Texture.Width / Options.Instance.Sprites.NormalFrames; + var textFrameHeight = SpritePanel.Texture.Height / Options.Instance.Sprites.Directions; + SpritePanel.SetTextureRect(0, 0, textFrameWidth, textFrameHeight); + SpritePanel.SetSize(Math.Min(textFrameWidth, 46), Math.Min(textFrameHeight, 46)); + Align.Center(SpritePanel); + } - public void UpdateMapList() - { - mMapList.Dispose(); - CreateMapList(); - AddMapListToTree(MapList.List, null); - } + private void _faceDropdown_ItemSelected(Base sender, ItemSelectedEventArgs arguments) + { + FacePanel.Texture = Globals.ContentManager.GetTexture( + Framework.Content.TextureType.Face, DropdownFace.Text); - private void AddMapListToTree(MapList mapList, TreeNode parent) + if (FacePanel.Texture == null) { - TreeNode tmpNode; - if (CheckboxChronological.IsChecked) - { - for (var i = MapList.OrderedMaps.Count - 1; i >= 0; i--) - { - tmpNode = mMapList.AddNode(MapList.OrderedMaps[i].Name); - tmpNode.UserData = MapList.OrderedMaps[i].MapId; - tmpNode.DoubleClicked += tmpNode_DoubleClicked; - tmpNode.Clicked += tmpNode_DoubleClicked; - } - } - else - { - foreach (var item in mapList.Items) - { - switch (item) - { - case MapListFolder folder: - tmpNode = parent?.AddNode(item.Name) ?? mMapList.AddNode(item.Name); - tmpNode.UserData = folder; - AddMapListToTree(folder.Children, tmpNode); - break; - case MapListMap map: - tmpNode = parent?.AddNode(item.Name) ?? mMapList.AddNode(item.Name); - tmpNode.UserData = map.MapId; - tmpNode.DoubleClicked += tmpNode_DoubleClicked; - tmpNode.Clicked += tmpNode_DoubleClicked; - break; - } - } - } + return; } - void _kickButton_Clicked(Base sender, ClickedEventArgs arguments) + var textFrameWidth = FacePanel.Texture.Width; + var textFrameHeight = FacePanel.Texture.Height; + FacePanel.SetTextureRect(0, 0, textFrameWidth, textFrameHeight); + FacePanel.SetSize(Math.Min(textFrameWidth, 46), Math.Min(textFrameHeight, 46)); + Align.Center(FacePanel); + } + + //Methods + public void SetName(string name) + { + TextboxName.Text = name; + } + + private void CreateMapList() + { + mMapList = new TreeControl(mAdminWindow); + mMapList.SetPosition(4f, 330); + mMapList.Width = mAdminWindow.Width - 8; + mMapList.Height = 80; + mMapList.RenderColor = Color.FromArgb(255, 255, 255, 255); + mMapList.MaximumSize = new Point(4096, 999999); + } + + public void UpdateMapList() + { + mMapList.Dispose(); + CreateMapList(); + AddMapListToTree(MapList.List, null); + } + + private void AddMapListToTree(MapList mapList, TreeNode parent) + { + TreeNode tmpNode; + if (CheckboxChronological.IsChecked) { - if (TextboxName.Text.Trim().Length > 0) + for (var i = MapList.OrderedMaps.Count - 1; i >= 0; i--) { - PacketSender.SendAdminAction(new KickAction(TextboxName.Text)); + tmpNode = mMapList.AddNode(MapList.OrderedMaps[i].Name); + tmpNode.UserData = MapList.OrderedMaps[i].MapId; + tmpNode.DoubleClicked += tmpNode_DoubleClicked; + tmpNode.Clicked += tmpNode_DoubleClicked; } } - - void _killButton_Clicked(Base sender, ClickedEventArgs arguments) + else { - if (TextboxName.Text.Trim().Length > 0) + foreach (var item in mapList.Items) { - PacketSender.SendAdminAction(new KillAction(TextboxName.Text)); + switch (item) + { + case MapListFolder folder: + tmpNode = parent?.AddNode(item.Name) ?? mMapList.AddNode(item.Name); + tmpNode.UserData = folder; + AddMapListToTree(folder.Children, tmpNode); + break; + case MapListMap map: + tmpNode = parent?.AddNode(item.Name) ?? mMapList.AddNode(item.Name); + tmpNode.UserData = map.MapId; + tmpNode.DoubleClicked += tmpNode_DoubleClicked; + tmpNode.Clicked += tmpNode_DoubleClicked; + break; + } } } + } - void _warpToMeButton_Clicked(Base sender, ClickedEventArgs arguments) + void _kickButton_Clicked(Base sender, ClickedEventArgs arguments) + { + if (TextboxName.Text.Trim().Length > 0) { - if (TextboxName.Text.Trim().Length > 0) - { - PacketSender.SendAdminAction(new WarpToMeAction(TextboxName.Text)); - } + PacketSender.SendAdminAction(new KickAction(TextboxName.Text)); } + } - void _warpMeToButton_Clicked(Base sender, ClickedEventArgs arguments) + void _killButton_Clicked(Base sender, ClickedEventArgs arguments) + { + if (TextboxName.Text.Trim().Length > 0) { - if (TextboxName.Text.Trim().Length > 0) - { - PacketSender.SendAdminAction(new WarpMeToAction(TextboxName.Text)); - } + PacketSender.SendAdminAction(new KillAction(TextboxName.Text)); } + } - void _overWorldReturn_Clicked(Base sender, ClickedEventArgs arguments) + void _warpToMeButton_Clicked(Base sender, ClickedEventArgs arguments) + { + if (TextboxName.Text.Trim().Length > 0) { - if (!string.IsNullOrEmpty(TextboxName.Text)) - { - PacketSender.SendAdminAction(new ReturnToOverworldAction(TextboxName.Text)); - } + PacketSender.SendAdminAction(new WarpToMeAction(TextboxName.Text)); } + } - void _muteButton_Clicked(Base sender, ClickedEventArgs arguments) + void _warpMeToButton_Clicked(Base sender, ClickedEventArgs arguments) + { + if (TextboxName.Text.Trim().Length > 0) { - if (TextboxName.Text.Trim().Length > 0) - { - mBanMuteWindow = new BanMuteBox(Strings.Admin.MuteCaption.ToString(TextboxName.Text), - Strings.Admin.MutePrompt.ToString(TextboxName.Text), true, MuteUser); - } + PacketSender.SendAdminAction(new WarpMeToAction(TextboxName.Text)); } + } - void MuteUser(object sender, EventArgs e) + void _overWorldReturn_Clicked(Base sender, ClickedEventArgs arguments) + { + if (!string.IsNullOrEmpty(TextboxName.Text)) { - PacketSender.SendAdminAction(new MuteAction(TextboxName.Text, mBanMuteWindow.GetDuration(), - mBanMuteWindow.GetReason(), mBanMuteWindow.BanIp())); - - mBanMuteWindow.Dispose(); + PacketSender.SendAdminAction(new ReturnToOverworldAction(TextboxName.Text)); } + } - void BanUser(object sender, EventArgs e) + void _muteButton_Clicked(Base sender, ClickedEventArgs arguments) + { + if (TextboxName.Text.Trim().Length > 0) { - PacketSender.SendAdminAction(new BanAction(TextboxName.Text, mBanMuteWindow.GetDuration(), - mBanMuteWindow.GetReason(), mBanMuteWindow.BanIp())); - - mBanMuteWindow.Dispose(); + mBanMuteWindow = new BanMuteBox(Strings.Admin.MuteCaption.ToString(TextboxName.Text), + Strings.Admin.MutePrompt.ToString(TextboxName.Text), true, MuteUser); } + } - void _banButton_Clicked(Base sender, ClickedEventArgs arguments) - { - if (string.IsNullOrWhiteSpace(TextboxName.Text)) - { - return; - } + void MuteUser(object sender, EventArgs e) + { + PacketSender.SendAdminAction(new MuteAction(TextboxName.Text, mBanMuteWindow.GetDuration(), + mBanMuteWindow.GetReason(), mBanMuteWindow.BanIp())); - var name = TextboxName.Text.Trim(); + mBanMuteWindow.Dispose(); + } - if (string.Equals(name, Globals.Me.Name, StringComparison.CurrentCultureIgnoreCase)) - { - return; - } + void BanUser(object sender, EventArgs e) + { + PacketSender.SendAdminAction(new BanAction(TextboxName.Text, mBanMuteWindow.GetDuration(), + mBanMuteWindow.GetReason(), mBanMuteWindow.BanIp())); - mBanMuteWindow = new BanMuteBox(Strings.Admin.BanCaption.ToString(name), - Strings.Admin.BanPrompt.ToString(TextboxName.Text), true, BanUser); - } + mBanMuteWindow.Dispose(); + } - private void _setFaceButton_Clicked(Base sender, ClickedEventArgs arguments) + void _banButton_Clicked(Base sender, ClickedEventArgs arguments) + { + if (string.IsNullOrWhiteSpace(TextboxName.Text)) { - if (TextboxName.Text.Trim().Length > 0) - { - PacketSender.SendAdminAction(new SetFaceAction(TextboxName.Text, DropdownFace.Text)); - } + return; } - void _unmuteButton_Clicked(Base sender, ClickedEventArgs arguments) - { - if (TextboxName.Text.Trim().Length > 0) - { - new InputBox(Strings.Admin.UnmuteCaption.ToString(TextboxName.Text), - Strings.Admin.UnmutePrompt.ToString(TextboxName.Text), true, InputBox.InputType.YesNo, UnmuteUser, - null, -1); - } - } + var name = TextboxName.Text.Trim(); - void _unbanButton_Clicked(Base sender, ClickedEventArgs arguments) + if (string.Equals(name, Globals.Me.Name, StringComparison.CurrentCultureIgnoreCase)) { - if (TextboxName.Text.Trim().Length > 0) - { - new InputBox(Strings.Admin.UnbanCaption.ToString(TextboxName.Text), - Strings.Admin.UnbanPrompt.ToString(TextboxName.Text), true, InputBox.InputType.YesNo, UnbanUser, - null, -1); - } + return; } - void UnmuteUser(object sender, EventArgs e) - { - PacketSender.SendAdminAction(new UnmuteAction(TextboxName.Text)); - } + mBanMuteWindow = new BanMuteBox(Strings.Admin.BanCaption.ToString(name), + Strings.Admin.BanPrompt.ToString(TextboxName.Text), true, BanUser); + } - void UnbanUser(object sender, EventArgs e) + private void _setFaceButton_Clicked(Base sender, ClickedEventArgs arguments) + { + if (TextboxName.Text.Trim().Length > 0) { - PacketSender.SendAdminAction(new UnbanAction(TextboxName.Text)); + PacketSender.SendAdminAction(new SetFaceAction(TextboxName.Text, DropdownFace.Text)); } + } - void _setSpriteButton_Clicked(Base sender, ClickedEventArgs arguments) + void _unmuteButton_Clicked(Base sender, ClickedEventArgs arguments) + { + if (TextboxName.Text.Trim().Length > 0) { - if (TextboxName.Text.Trim().Length > 0) - { - PacketSender.SendAdminAction(new SetSpriteAction(TextboxName.Text, DropdownSprite.Text)); - } + new InputBox(Strings.Admin.UnmuteCaption.ToString(TextboxName.Text), + Strings.Admin.UnmutePrompt.ToString(TextboxName.Text), true, InputBox.InputType.YesNo, UnmuteUser, + null, -1); } + } - void _setPowerButton_Clicked(Base sender, ClickedEventArgs arguments) + void _unbanButton_Clicked(Base sender, ClickedEventArgs arguments) + { + if (TextboxName.Text.Trim().Length > 0) { - if (TextboxName.Text.Trim().Length > 0) - { - PacketSender.SendAdminAction( - new SetAccessAction(TextboxName.Text, DropdownAccess.SelectedItem.UserData.ToString()) - ); - } + new InputBox(Strings.Admin.UnbanCaption.ToString(TextboxName.Text), + Strings.Admin.UnbanPrompt.ToString(TextboxName.Text), true, InputBox.InputType.YesNo, UnbanUser, + null, -1); } + } - void _chkChronological_CheckChanged(Base sender, EventArgs arguments) - { - UpdateMapList(); - } + void UnmuteUser(object sender, EventArgs e) + { + PacketSender.SendAdminAction(new UnmuteAction(TextboxName.Text)); + } - static void tmpNode_DoubleClicked(Base sender, ClickedEventArgs arguments) - { - PacketSender.SendAdminAction(new WarpToMapAction((Guid) ((TreeNode) sender).UserData)); - } + void UnbanUser(object sender, EventArgs e) + { + PacketSender.SendAdminAction(new UnbanAction(TextboxName.Text)); + } - public void Update() + void _setSpriteButton_Clicked(Base sender, ClickedEventArgs arguments) + { + if (TextboxName.Text.Trim().Length > 0) { + PacketSender.SendAdminAction(new SetSpriteAction(TextboxName.Text, DropdownSprite.Text)); } + } - public void Show() + void _setPowerButton_Clicked(Base sender, ClickedEventArgs arguments) + { + if (TextboxName.Text.Trim().Length > 0) { - mAdminWindow.IsHidden = false; + PacketSender.SendAdminAction( + new SetAccessAction(TextboxName.Text, DropdownAccess.SelectedItem.UserData.ToString()) + ); } + } - public bool IsVisible() - { - return !mAdminWindow.IsHidden; - } + void _chkChronological_CheckChanged(Base sender, EventArgs arguments) + { + UpdateMapList(); + } - public void Hide() - { - mAdminWindow.IsHidden = true; - } + static void tmpNode_DoubleClicked(Base sender, ClickedEventArgs arguments) + { + PacketSender.SendAdminAction(new WarpToMapAction((Guid) ((TreeNode) sender).UserData)); + } + + public void Update() + { + } + + public void Show() + { + mAdminWindow.IsHidden = false; + } + + public bool IsVisible() + { + return !mAdminWindow.IsHidden; + } + + public void Hide() + { + mAdminWindow.IsHidden = true; } } diff --git a/Intersect.Client/Interface/Game/AnnouncementWindow.cs b/Intersect.Client/Interface/Game/AnnouncementWindow.cs index 5b495044c0..5ce4683ec7 100644 --- a/Intersect.Client/Interface/Game/AnnouncementWindow.cs +++ b/Intersect.Client/Interface/Game/AnnouncementWindow.cs @@ -4,93 +4,91 @@ using Intersect.Utilities; -namespace Intersect.Client.Interface.Game +namespace Intersect.Client.Interface.Game; + +/// +/// The GUI class for the Announcement Window that can pop up on-screen during gameplay. +/// +public partial class AnnouncementWindow { - /// - /// The GUI class for the Announcement Window that can pop up on-screen during gameplay. - /// - public partial class AnnouncementWindow - { - //Controls - private Canvas mGameCanvas; + //Controls + private Canvas mGameCanvas; - private ImagePanel mPicture; + private ImagePanel mPicture; - private Label mLabel; + private Label mLabel; - private string mLabelText; + private string mLabelText; - private long mDisplayUntil = 0; + private long mDisplayUntil = 0; - /// - /// Indicates whether the control is hidden. - /// - public bool IsHidden - { - get { return mPicture.IsHidden; } - set { mPicture.IsHidden = value; } - } + /// + /// Indicates whether the control is hidden. + /// + public bool IsHidden + { + get { return mPicture.IsHidden; } + set { mPicture.IsHidden = value; } + } - /// - /// Create a new instance of the class. - /// - /// The to render this control on. - public AnnouncementWindow(Canvas gameCanvas) - { - mGameCanvas = gameCanvas; - mPicture = new ImagePanel(gameCanvas, "AnnouncementWindow"); - mLabel = new Label(mPicture, "AnnouncementLabel"); - - mPicture.LoadJsonUi(GameContentManager.UI.InGame, Graphics.Renderer.GetResolutionString()); - } + /// + /// Create a new instance of the class. + /// + /// The to render this control on. + public AnnouncementWindow(Canvas gameCanvas) + { + mGameCanvas = gameCanvas; + mPicture = new ImagePanel(gameCanvas, "AnnouncementWindow"); + mLabel = new Label(mPicture, "AnnouncementLabel"); + + mPicture.LoadJsonUi(GameContentManager.UI.InGame, Graphics.Renderer.GetResolutionString()); + } - /// - /// Update this control.. - /// - public void Update() + /// + /// Update this control.. + /// + public void Update() + { + // Only update when we're visible to the user. + if (!mPicture.IsHidden) { - // Only update when we're visible to the user. - if (!mPicture.IsHidden) - { - mLabel.Text = mLabelText; + mLabel.Text = mLabelText; - // Are we still supposed to be visible? - if (Timing.Global.Milliseconds > mDisplayUntil) - { - Hide(); - } + // Are we still supposed to be visible? + if (Timing.Global.Milliseconds > mDisplayUntil) + { + Hide(); } } + } - /// - /// Display an announcement. - /// - /// The text to display. - /// The time for which to display the announcement. - public void ShowAnnouncement(string announcementText, long displayTime) - { - mLabelText = announcementText; - mDisplayUntil = Timing.Global.Milliseconds + displayTime; - Show(); - } - - /// - /// Hides the control. - /// - public void Hide() - { - mPicture.Hide(); - } + /// + /// Display an announcement. + /// + /// The text to display. + /// The time for which to display the announcement. + public void ShowAnnouncement(string announcementText, long displayTime) + { + mLabelText = announcementText; + mDisplayUntil = Timing.Global.Milliseconds + displayTime; + Show(); + } - /// - /// Shows the control. - /// - public void Show() - { - mPicture.Show(); - } + /// + /// Hides the control. + /// + public void Hide() + { + mPicture.Hide(); + } + /// + /// Shows the control. + /// + public void Show() + { + mPicture.Show(); } } \ No newline at end of file diff --git a/Intersect.Client/Interface/Game/Bag/BagItem.cs b/Intersect.Client/Interface/Game/Bag/BagItem.cs index 665667071f..ccfdd94c4e 100644 --- a/Intersect.Client/Interface/Game/Bag/BagItem.cs +++ b/Intersect.Client/Interface/Game/Bag/BagItem.cs @@ -10,164 +10,156 @@ using Intersect.GameObjects; using Intersect.Utilities; -namespace Intersect.Client.Interface.Game.Bag +namespace Intersect.Client.Interface.Game.Bag; + + +public partial class BagItem { - public partial class BagItem - { + private static int sItemXPadding = 4; - private static int sItemXPadding = 4; + private static int sItemYPadding = 4; - private static int sItemYPadding = 4; + public ImagePanel Container; - public ImagePanel Container; + public bool IsDragging; - public bool IsDragging; + //Drag/Drop References + private BagWindow mBagWindow; - //Drag/Drop References - private BagWindow mBagWindow; + //Dragging + private bool mCanDrag; - //Dragging - private bool mCanDrag; + private long mClickTime; - private long mClickTime; + private Guid mCurrentItemId; - private Guid mCurrentItemId; + private ItemDescriptionWindow mDescWindow; - private ItemDescriptionWindow mDescWindow; + private Draggable mDragIcon; - private Draggable mDragIcon; + //Mouse Event Variables + private bool mMouseOver; - //Mouse Event Variables - private bool mMouseOver; + private int mMouseX = -1; - private int mMouseX = -1; + private int mMouseY = -1; - private int mMouseY = -1; + //Slot info + private int mMySlot; - //Slot info - private int mMySlot; + public ImagePanel Pnl; - public ImagePanel Pnl; + public BagItem(BagWindow bagWindow, int index) + { + mBagWindow = bagWindow; + mMySlot = index; + } + + public void Setup() + { + Pnl = new ImagePanel(Container, "BagItemIcon"); + Pnl.HoverEnter += pnl_HoverEnter; + Pnl.HoverLeave += pnl_HoverLeave; + Pnl.RightClicked += Pnl_RightClicked; + Pnl.DoubleClicked += Pnl_DoubleClicked; + Pnl.Clicked += pnl_Clicked; + } - public BagItem(BagWindow bagWindow, int index) + private void Pnl_RightClicked(Base sender, ClickedEventArgs arguments) + { + if (ClientConfiguration.Instance.EnableContextMenus) { - mBagWindow = bagWindow; - mMySlot = index; + mBagWindow.OpenContextMenu(mMySlot); } + else + { + Pnl_DoubleClicked(sender, arguments); + } + } - public void Setup() + private void Pnl_DoubleClicked(Base sender, ClickedEventArgs arguments) + { + if (Globals.InBag) { - Pnl = new ImagePanel(Container, "BagItemIcon"); - Pnl.HoverEnter += pnl_HoverEnter; - Pnl.HoverLeave += pnl_HoverLeave; - Pnl.RightClicked += Pnl_RightClicked; - Pnl.DoubleClicked += Pnl_DoubleClicked; - Pnl.Clicked += pnl_Clicked; + Globals.Me.TryRetreiveBagItem(mMySlot, -1); } + } - private void Pnl_RightClicked(Base sender, ClickedEventArgs arguments) + void pnl_Clicked(Base sender, ClickedEventArgs arguments) + { + mClickTime = Timing.Global.MillisecondsUtc + 500; + } + + void pnl_HoverLeave(Base sender, EventArgs arguments) + { + mMouseOver = false; + mMouseX = -1; + mMouseY = -1; + if (mDescWindow != null) { - if (ClientConfiguration.Instance.EnableContextMenus) - { - mBagWindow.OpenContextMenu(mMySlot); - } - else - { - Pnl_DoubleClicked(sender, arguments); - } + mDescWindow.Dispose(); + mDescWindow = null; } + } - private void Pnl_DoubleClicked(Base sender, ClickedEventArgs arguments) + void pnl_HoverEnter(Base sender, EventArgs arguments) + { + if (InputHandler.MouseFocus != null) { - if (Globals.InBag) - { - Globals.Me.TryRetreiveBagItem(mMySlot, -1); - } + return; } - void pnl_Clicked(Base sender, ClickedEventArgs arguments) + mMouseOver = true; + mCanDrag = true; + if (Globals.InputManager.MouseButtonDown(MouseButtons.Left)) { - mClickTime = Timing.Global.MillisecondsUtc + 500; + mCanDrag = false; + + return; } - void pnl_HoverLeave(Base sender, EventArgs arguments) + if (mDescWindow != null) { - mMouseOver = false; - mMouseX = -1; - mMouseY = -1; - if (mDescWindow != null) - { - mDescWindow.Dispose(); - mDescWindow = null; - } + mDescWindow.Dispose(); + mDescWindow = null; } - void pnl_HoverEnter(Base sender, EventArgs arguments) + if (Globals.Bag[mMySlot]?.Base != null) { - if (InputHandler.MouseFocus != null) - { - return; - } - - mMouseOver = true; - mCanDrag = true; - if (Globals.InputManager.MouseButtonDown(MouseButtons.Left)) - { - mCanDrag = false; - - return; - } - - if (mDescWindow != null) - { - mDescWindow.Dispose(); - mDescWindow = null; - } - - if (Globals.Bag[mMySlot]?.Base != null) - { - mDescWindow = new ItemDescriptionWindow( - Globals.Bag[mMySlot].Base, Globals.Bag[mMySlot].Quantity, mBagWindow.X, mBagWindow.Y, - Globals.Bag[mMySlot].ItemProperties - ); - } + mDescWindow = new ItemDescriptionWindow( + Globals.Bag[mMySlot].Base, Globals.Bag[mMySlot].Quantity, mBagWindow.X, mBagWindow.Y, + Globals.Bag[mMySlot].ItemProperties + ); } + } - public FloatRect RenderBounds() + public FloatRect RenderBounds() + { + var rect = new FloatRect() { - var rect = new FloatRect() - { - X = Pnl.LocalPosToCanvas(new Point(0, 0)).X, - Y = Pnl.LocalPosToCanvas(new Point(0, 0)).Y, - Width = Pnl.Width, - Height = Pnl.Height - }; + X = Pnl.LocalPosToCanvas(new Point(0, 0)).X, + Y = Pnl.LocalPosToCanvas(new Point(0, 0)).Y, + Width = Pnl.Width, + Height = Pnl.Height + }; - return rect; - } + return rect; + } - public void Update() + public void Update() + { + if (Globals.Bag[mMySlot].ItemId != mCurrentItemId) { - if (Globals.Bag[mMySlot].ItemId != mCurrentItemId) + mCurrentItemId = Globals.Bag[mMySlot].ItemId; + var item = ItemBase.Get(Globals.Bag[mMySlot].ItemId); + if (item != null) { - mCurrentItemId = Globals.Bag[mMySlot].ItemId; - var item = ItemBase.Get(Globals.Bag[mMySlot].ItemId); - if (item != null) + var itemTex = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Item, item.Icon); + if (itemTex != null) { - var itemTex = Globals.ContentManager.GetTexture(Framework.Content.TextureType.Item, item.Icon); - if (itemTex != null) - { - Pnl.Texture = itemTex; - Pnl.RenderColor = item.Color; - } - else - { - if (Pnl.Texture != null) - { - Pnl.Texture = null; - } - } + Pnl.Texture = itemTex; + Pnl.RenderColor = item.Color; } else { @@ -177,130 +169,136 @@ public void Update() } } } + else + { + if (Pnl.Texture != null) + { + Pnl.Texture = null; + } + } + } - if (!IsDragging) + if (!IsDragging) + { + if (mMouseOver) { - if (mMouseOver) + if (!Globals.InputManager.MouseButtonDown(MouseButtons.Left)) { - if (!Globals.InputManager.MouseButtonDown(MouseButtons.Left)) + mCanDrag = true; + mMouseX = -1; + mMouseY = -1; + if (Timing.Global.MillisecondsUtc < mClickTime) { - mCanDrag = true; - mMouseX = -1; - mMouseY = -1; - if (Timing.Global.MillisecondsUtc < mClickTime) - { - mClickTime = 0; - } + mClickTime = 0; } - else + } + else + { + if (mCanDrag && Draggable.Active == null) { - if (mCanDrag && Draggable.Active == null) + if (mMouseX == -1 || mMouseY == -1) { - if (mMouseX == -1 || mMouseY == -1) - { - mMouseX = InputHandler.MousePosition.X - Pnl.LocalPosToCanvas(new Point(0, 0)).X; - mMouseY = InputHandler.MousePosition.Y - Pnl.LocalPosToCanvas(new Point(0, 0)).Y; - } - else - { - var xdiff = mMouseX - - (InputHandler.MousePosition.X - Pnl.LocalPosToCanvas(new Point(0, 0)).X); + mMouseX = InputHandler.MousePosition.X - Pnl.LocalPosToCanvas(new Point(0, 0)).X; + mMouseY = InputHandler.MousePosition.Y - Pnl.LocalPosToCanvas(new Point(0, 0)).Y; + } + else + { + var xdiff = mMouseX - + (InputHandler.MousePosition.X - Pnl.LocalPosToCanvas(new Point(0, 0)).X); - var ydiff = mMouseY - - (InputHandler.MousePosition.Y - Pnl.LocalPosToCanvas(new Point(0, 0)).Y); + var ydiff = mMouseY - + (InputHandler.MousePosition.Y - Pnl.LocalPosToCanvas(new Point(0, 0)).Y); - if (Math.Sqrt(Math.Pow(xdiff, 2) + Math.Pow(ydiff, 2)) > 5) - { - IsDragging = true; - mDragIcon = new Draggable( - Pnl.LocalPosToCanvas(new Point(0, 0)).X + mMouseX, - Pnl.LocalPosToCanvas(new Point(0, 0)).X + mMouseY, Pnl.Texture, Pnl.RenderColor - ); - } + if (Math.Sqrt(Math.Pow(xdiff, 2) + Math.Pow(ydiff, 2)) > 5) + { + IsDragging = true; + mDragIcon = new Draggable( + Pnl.LocalPosToCanvas(new Point(0, 0)).X + mMouseX, + Pnl.LocalPosToCanvas(new Point(0, 0)).X + mMouseY, Pnl.Texture, Pnl.RenderColor + ); } } } } } - else + } + else + { + if (mDragIcon.Update()) { - if (mDragIcon.Update()) + //Drug the item and now we stopped + IsDragging = false; + var dragRect = new FloatRect( + mDragIcon.X - sItemXPadding / 2, mDragIcon.Y - sItemYPadding / 2, sItemXPadding / 2 + 32, + sItemYPadding / 2 + 32 + ); + + float bestIntersect = 0; + var bestIntersectIndex = -1; + + //So we picked up an item and then dropped it. Lets see where we dropped it to. + //Check inventory first. + if (mBagWindow.RenderBounds().IntersectsWith(dragRect)) { - //Drug the item and now we stopped - IsDragging = false; - var dragRect = new FloatRect( - mDragIcon.X - sItemXPadding / 2, mDragIcon.Y - sItemYPadding / 2, sItemXPadding / 2 + 32, - sItemYPadding / 2 + 32 - ); - - float bestIntersect = 0; - var bestIntersectIndex = -1; - - //So we picked up an item and then dropped it. Lets see where we dropped it to. - //Check inventory first. - if (mBagWindow.RenderBounds().IntersectsWith(dragRect)) + for (var i = 0; i < Globals.Bag.Length; i++) { - for (var i = 0; i < Globals.Bag.Length; i++) + if (mBagWindow.Items[i].RenderBounds().IntersectsWith(dragRect)) { - if (mBagWindow.Items[i].RenderBounds().IntersectsWith(dragRect)) + if (FloatRect.Intersect(mBagWindow.Items[i].RenderBounds(), dragRect).Width * + FloatRect.Intersect(mBagWindow.Items[i].RenderBounds(), dragRect).Height > + bestIntersect) { - if (FloatRect.Intersect(mBagWindow.Items[i].RenderBounds(), dragRect).Width * - FloatRect.Intersect(mBagWindow.Items[i].RenderBounds(), dragRect).Height > - bestIntersect) - { - bestIntersect = - FloatRect.Intersect(mBagWindow.Items[i].RenderBounds(), dragRect).Width * - FloatRect.Intersect(mBagWindow.Items[i].RenderBounds(), dragRect).Height; + bestIntersect = + FloatRect.Intersect(mBagWindow.Items[i].RenderBounds(), dragRect).Width * + FloatRect.Intersect(mBagWindow.Items[i].RenderBounds(), dragRect).Height; - bestIntersectIndex = i; - } + bestIntersectIndex = i; } } + } - if (bestIntersectIndex > -1) + if (bestIntersectIndex > -1) + { + if (mMySlot != bestIntersectIndex) { - if (mMySlot != bestIntersectIndex) - { - //Try to swap.... - PacketSender.SendMoveBagItems(mMySlot, bestIntersectIndex); - } + //Try to swap.... + PacketSender.SendMoveBagItems(mMySlot, bestIntersectIndex); } } - else - { - var invWindow = Interface.GameUi.GameMenu.GetInventoryWindow(); + } + else + { + var invWindow = Interface.GameUi.GameMenu.GetInventoryWindow(); - if (invWindow.RenderBounds().IntersectsWith(dragRect)) + if (invWindow.RenderBounds().IntersectsWith(dragRect)) + { + for (var i = 0; i < Options.MaxInvItems; i++) { - for (var i = 0; i < Options.MaxInvItems; i++) + if (invWindow.Items[i].RenderBounds().IntersectsWith(dragRect)) { - if (invWindow.Items[i].RenderBounds().IntersectsWith(dragRect)) + if (FloatRect.Intersect(invWindow.Items[i].RenderBounds(), dragRect).Width * + FloatRect.Intersect(invWindow.Items[i].RenderBounds(), dragRect).Height > + bestIntersect) { - if (FloatRect.Intersect(invWindow.Items[i].RenderBounds(), dragRect).Width * - FloatRect.Intersect(invWindow.Items[i].RenderBounds(), dragRect).Height > - bestIntersect) - { - bestIntersect = - FloatRect.Intersect(invWindow.Items[i].RenderBounds(), dragRect).Width * - FloatRect.Intersect(invWindow.Items[i].RenderBounds(), dragRect).Height; - - bestIntersectIndex = i; - } + bestIntersect = + FloatRect.Intersect(invWindow.Items[i].RenderBounds(), dragRect).Width * + FloatRect.Intersect(invWindow.Items[i].RenderBounds(), dragRect).Height; + + bestIntersectIndex = i; } } + } - if (bestIntersectIndex > -1) - { - Globals.Me.TryRetreiveBagItem(mMySlot, bestIntersectIndex); - } + if (bestIntersectIndex > -1) + { + Globals.Me.TryRetreiveBagItem(mMySlot, bestIntersectIndex); } } - - mDragIcon.Dispose(); } + + mDragIcon.Dispose(); } } - } } diff --git a/Intersect.Client/Interface/Game/Bag/BagWindow.cs b/Intersect.Client/Interface/Game/Bag/BagWindow.cs index 5a3f4552c0..5e8173aa18 100644 --- a/Intersect.Client/Interface/Game/Bag/BagWindow.cs +++ b/Intersect.Client/Interface/Game/Bag/BagWindow.cs @@ -6,189 +6,187 @@ using Intersect.Client.Localization; using Intersect.GameObjects; -namespace Intersect.Client.Interface.Game.Bag +namespace Intersect.Client.Interface.Game.Bag; + + +public partial class BagWindow { - public partial class BagWindow - { + private static int sItemXPadding = 4; - private static int sItemXPadding = 4; + private static int sItemYPadding = 4; - private static int sItemYPadding = 4; + public List Items = new List(); - public List Items = new List(); + //Controls + private WindowControl mBagWindow; - //Controls - private WindowControl mBagWindow; + private ScrollControl mItemContainer; - private ScrollControl mItemContainer; + private List