From c76dc6f91fd6a33e366bd05cfee66032bf1a7ff3 Mon Sep 17 00:00:00 2001 From: im-ny-99 Date: Thu, 19 Mar 2026 11:53:08 +0700 Subject: [PATCH] Add files via upload --- Beasts.Render.cs | 805 +++++++++++++++++++++++----------------------- BeastsSettings.cs | 292 ++++++++--------- 2 files changed, 554 insertions(+), 543 deletions(-) diff --git a/Beasts.Render.cs b/Beasts.Render.cs index 67767fd..3dbe214 100755 --- a/Beasts.Render.cs +++ b/Beasts.Render.cs @@ -1,398 +1,407 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using Beasts.Data; -using Beasts.ExileCore; -using ExileCore.PoEMemory.Components; -using ExileCore.PoEMemory.Elements; -using ExileCore.PoEMemory.Elements.InventoryElements; -using ExileCore.Shared.Enums; -using ExileCore.Shared.Helpers; -using ImGuiNET; -using SharpDX; -using Vector2 = System.Numerics.Vector2; -using Vector3 = System.Numerics.Vector3; - -namespace Beasts; - -public partial class Beasts -{ - private const int TileToGridConversion = 23; - private const int TileToWorldConversion = 250; - private const float GridToWorldMultiplier = TileToWorldConversion / (float)TileToGridConversion; - private const double CameraAngle = 38.7 * Math.PI / 180; - private static readonly float CameraAngleCos = (float)Math.Cos(CameraAngle); - private static readonly float CameraAngleSin = (float)Math.Sin(CameraAngle); - - private double _mapScale; - private SharpDX.RectangleF _rect; - private ImDrawListPtr _backGroundWindowPtr; - - public override void Render() - { - DrawInGameBeasts(); - if (Settings.ShowBeastPricesOnLargeMap.Value) DrawBeastsOnLargeMap(); - if (Settings.ShowBestiaryPanel.Value) DrawBestiaryPanel(); - if (Settings.ShowTrackedBeastsWindow.Value) DrawBeastsWindow(); - if (Settings.ShowCapturedBeastsInInventory.Value) DrawInventoryBeasts(); - if (Settings.ShowCapturedBeastsInStash.Value) DrawStashBeasts(); - } - - private void DrawBeastsOnLargeMap() - { - var ingameUi = GameController.IngameState.IngameUi; - - _rect = GameController.Window.GetWindowRectangle() with { Location = SharpDX.Vector2.Zero }; - if (ingameUi.OpenRightPanel.IsVisible) - { - _rect.Right = ingameUi.OpenRightPanel.GetClientRectCache.Left; - } - - if (ingameUi.OpenLeftPanel.IsVisible) - { - _rect.Left = ingameUi.OpenLeftPanel.GetClientRectCache.Right; - } - - ImGui.SetNextWindowSize(new Vector2(_rect.Width, _rect.Height)); - ImGui.SetNextWindowPos(new Vector2(_rect.Left, _rect.Top)); - - ImGui.Begin("beasts_radar_background", - ImGuiWindowFlags.NoDecoration | - ImGuiWindowFlags.NoInputs | - ImGuiWindowFlags.NoMove | - ImGuiWindowFlags.NoScrollWithMouse | - ImGuiWindowFlags.NoSavedSettings | - ImGuiWindowFlags.NoFocusOnAppearing | - ImGuiWindowFlags.NoBringToFrontOnFocus | - ImGuiWindowFlags.NoBackground); - - // Use foreground draw list so price labels stay above other plugin map icons. - _backGroundWindowPtr = ImGui.GetForegroundDrawList(); - - var map = ingameUi.Map; - var largeMap = map.LargeMap.AsObject(); - if (largeMap.IsVisible) - { - var mapCenter = largeMap.MapCenter; - _mapScale = largeMap.MapScale; - DrawBeastsOnMap(mapCenter); - } - - ImGui.End(); - } - - private void DrawBeastsOnMap(Vector2 mapCenter) - { - var player = GameController.Game.IngameState.Data.LocalPlayer; - var playerRender = player?.GetComponent(); - var playerPositioned = player?.GetComponent(); - if (playerRender == null || playerPositioned == null) return; - - var playerPosition = new Vector2(playerPositioned.GridPosNum.X, playerPositioned.GridPosNum.Y); - var playerHeight = -playerRender.RenderStruct.Height; - var heightData = GameController.IngameState.Data.RawTerrainHeightData; - - foreach (var trackedBeast in _trackedBeasts) - { - var entity = trackedBeast.Value; - var positioned = entity.GetComponent(); - if (positioned == null) continue; - - var beast = BeastsDatabase.AllBeasts.FirstOrDefault(b => entity.Metadata == b.Path); - if (beast == null) continue; - if (Settings.Beasts.All(b => b.Path != beast.Path)) continue; - - var mapPos = EntityToMapPos(positioned, playerPosition, playerHeight, heightData, mapCenter); - - if (Settings.BeastPrices.TryGetValue(beast.DisplayName, out var price) && price > 0) - { - var text = $"{price.ToString(CultureInfo.InvariantCulture)}c"; - var textSize = Graphics.MeasureText(text); - var textOffset = textSize / 2f; - - var bgPadding = new Vector2(4, 2); - var bgColor = new Color(0, 0, 0, 180); - DrawBox(mapPos - textOffset - bgPadding, mapPos + textOffset + bgPadding, bgColor); - - var color = GetSpecialBeastColor(beast.DisplayName); - DrawText(text, mapPos - textOffset, color); - } - } - - // Draw yellow beasts on map - foreach (var trackedYellow in _trackedYellowBeasts) - { - var entity = trackedYellow.Value; - var positioned = entity.GetComponent(); - if (positioned == null) continue; - - var mapPos = EntityToMapPos(positioned, playerPosition, playerHeight, heightData, mapCenter); - - var renderName = entity.GetComponent()?.Name ?? "Yellow Beast"; - var text = renderName; - var textSize = Graphics.MeasureText(text); - var textOffset = textSize / 2f; - - var bgPadding = new Vector2(4, 2); - DrawBox(mapPos - textOffset - bgPadding, mapPos + textOffset + bgPadding, new Color(0, 0, 0, 180)); - DrawText(text, mapPos - textOffset, new Color(255, 250, 0)); - } - } - - private Vector2 EntityToMapPos(Positioned positioned, Vector2 playerPosition, float playerHeight, float[][] heightData, Vector2 mapCenter) - { - var beastPosition = new Vector2(positioned.GridPosNum.X, positioned.GridPosNum.Y); - var beastGridPos = positioned.GridPosNum; - - float beastHeight = 0; - int beastX = (int)beastGridPos.X; - int beastY = (int)beastGridPos.Y; - if (heightData != null && beastY >= 0 && beastY < heightData.Length - && beastX >= 0 && beastX < heightData[beastY].Length) - { - beastHeight = heightData[beastY][beastX]; - } - - var mapDelta = TranslateGridDeltaToMapDelta(beastPosition - playerPosition, playerHeight + beastHeight); - return mapCenter + mapDelta; - } - - private Vector2 TranslateGridDeltaToMapDelta(Vector2 delta, float deltaZ) - { - deltaZ /= GridToWorldMultiplier; - return (float)_mapScale * new Vector2((delta.X - delta.Y) * CameraAngleCos, - (deltaZ - (delta.X + delta.Y)) * CameraAngleSin); - } - - private void DrawBox(Vector2 p0, Vector2 p1, Color color) - { - _backGroundWindowPtr.AddRectFilled(p0, p1, - ImGui.ColorConvertFloat4ToU32(new System.Numerics.Vector4(color.R / 255f, color.G / 255f, - color.B / 255f, color.A / 255f))); - } - - private void DrawText(string text, Vector2 pos, Color color) - { - _backGroundWindowPtr.AddText(pos, - ImGui.ColorConvertFloat4ToU32(new System.Numerics.Vector4(color.R / 255f, color.G / 255f, - color.B / 255f, color.A / 255f)), text); - } - - private void DrawInGameBeasts() - { - foreach (var trackedBeast in _trackedBeasts - .Select(beast => new { Positioned = beast.Value.GetComponent(), beast.Value.Metadata }) - .Where(beast => beast.Positioned != null)) - { - var beast = BeastsDatabase.AllBeasts.First(beast => trackedBeast.Metadata == beast.Path); - - if (Settings.Beasts.All(b => b.Path != beast.Path)) continue; - var pos = GameController.IngameState.Data.ToWorldWithTerrainHeight(trackedBeast.Positioned.GridPosition); - Graphics.DrawText(beast.DisplayName, GameController.IngameState.Camera.WorldToScreen(pos), Color.White, - FontAlign.Center); - - DrawFilledCircleInWorldPosition(pos, 100, GetSpecialBeastColor(beast.DisplayName)); - } - - // Draw yellow beasts in world - foreach (var trackedYellow in _trackedYellowBeasts) - { - var entity = trackedYellow.Value; - var positioned = entity.GetComponent(); - if (positioned == null) continue; - - var renderName = entity.GetComponent()?.Name ?? "Yellow Beast"; - var pos = GameController.IngameState.Data.ToWorldWithTerrainHeight(positioned.GridPosition); - Graphics.DrawText(renderName, GameController.IngameState.Camera.WorldToScreen(pos), new Color(255, 250, 0), - FontAlign.Center); - - DrawFilledCircleInWorldPosition(pos, 100, new Color(255, 250, 0)); - } - } - - private static Color GetSpecialBeastColor(string beastName) - { - if (beastName.Contains("Vivid")) - { - return new Color(255, 250, 0); - } - - if (beastName.Contains("Wild")) - { - return new Color(255, 0, 235); - } - - if (beastName.Contains("Primal")) - { - return new Color(0, 245, 255); - } - - if (beastName.Contains("Black")) - { - return new Color(255, 255, 255); - } - - return Color.Red; - } - - private void DrawBestiaryPanel() - { - var bestiary = GameController.IngameState.IngameUi.GetBestiaryPanel(); - if (bestiary == null || bestiary.IsVisible == false) return; - - var capturedBeastsPanel = bestiary.CapturedBeastsPanel; - if (capturedBeastsPanel == null || capturedBeastsPanel.IsVisible == false) return; - - var beasts = bestiary.CapturedBeastsPanel.CapturedBeasts; - foreach (var beast in beasts) - { - try - { - var beastMetadata = Settings.Beasts.Find(b => b.DisplayName == beast.DisplayName); - if (beastMetadata == null) continue; - if (!Settings.BeastPrices.ContainsKey(beastMetadata.DisplayName)) continue; - - var center = new Vector2(beast.GetClientRect().Center.X, beast.GetClientRect().Center.Y); - - Graphics.DrawBox(beast.GetClientRect(), new Color(0, 0, 0, 0.5f)); - Graphics.DrawFrame(beast.GetClientRect(), Color.White, 2); - Graphics.DrawText(beastMetadata.DisplayName, center, Color.White, FontAlign.Center); - - var text = Settings.BeastPrices[beastMetadata.DisplayName].ToString(CultureInfo.InvariantCulture) + "c"; - var textPos = center + new Vector2(0, 20); - Graphics.DrawText(text, textPos, Color.White, FontAlign.Center); - } - catch (Exception e) - { - // ignored - } - } - } - - private void DrawBeastsWindow() - { - ImGui.SetNextWindowSize(new Vector2(0, 0)); - ImGui.SetNextWindowBgAlpha(0.6f); - ImGui.Begin("Beasts Window", ImGuiWindowFlags.NoDecoration); - - if (ImGui.BeginTable("Beasts Table", 2, - ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersOuter | ImGuiTableFlags.BordersV)) - { - ImGui.TableSetupColumn("Price", ImGuiTableColumnFlags.WidthFixed, 48); - ImGui.TableSetupColumn("Beast"); - - foreach (var beastMetadata in _trackedBeasts - .Select(trackedBeast => trackedBeast.Value) - .Select(beast => Settings.Beasts.Find(b => b.Path == beast.Metadata)) - .Where(beastMetadata => beastMetadata != null)) - { - ImGui.TableNextRow(); - - ImGui.TableNextColumn(); - - ImGui.Text(Settings.BeastPrices.TryGetValue(beastMetadata.DisplayName, out var price) - ? $"{price.ToString(CultureInfo.InvariantCulture)}c" - : "0c"); - - ImGui.TableNextColumn(); - - ImGui.Text(beastMetadata.DisplayName); - foreach (var craft in beastMetadata.Crafts) - { - ImGui.Text(craft); - } - } - - // Yellow beasts in tracking window - foreach (var trackedYellow in _trackedYellowBeasts) - { - var entity = trackedYellow.Value; - var renderName = entity.GetComponent()?.Name ?? "Yellow Beast"; - - ImGui.TableNextRow(); - ImGui.TableNextColumn(); - ImGui.TextColored(new System.Numerics.Vector4(1f, 0.98f, 0f, 1f), "-"); - ImGui.TableNextColumn(); - ImGui.TextColored(new System.Numerics.Vector4(1f, 0.98f, 0f, 1f), renderName); - } - - ImGui.EndTable(); - } - - ImGui.End(); - } - - private void DrawInventoryBeasts() - { - var inventory = GameController.Game.IngameState.IngameUi.InventoryPanel[InventoryIndex.PlayerInventory]; - if (!inventory.IsVisible) return; - - DrawCapturedBeasts(inventory.VisibleInventoryItems); - } - - private void DrawStashBeasts() - { - var stash = GameController.Game.IngameState.IngameUi.StashElement; - if (stash == null || !stash.IsVisible) return; - - var visibleStash = stash.VisibleStash; - if (visibleStash == null) return; - - var items = visibleStash.VisibleInventoryItems; - if (items == null) return; - - DrawCapturedBeasts(items); - } - - private void DrawCapturedBeasts(IList items) - { - if (items == null || items.Count == 0) return; - - foreach (var item in items) - { - if (item?.Item == null) continue; - if (item.Item.Metadata != "Metadata/Items/Currency/CurrencyItemisedCapturedMonster") continue; - - var itemRect = item.GetClientRect(); - var monster = item.Item.GetComponent(); - var monsterName = monster?.MonsterVariety?.MonsterName; - - if (!string.IsNullOrEmpty(monsterName) && Settings.BeastPrices.TryGetValue(monsterName, out var price)) - { - Graphics.DrawBox(itemRect, new Color(0, 0, 0, 0.1f)); - Graphics.DrawText($"{price.ToString(CultureInfo.InvariantCulture)}c", itemRect.Center, - Color.White, FontAlign.Center); - } - else - { - Graphics.DrawBox(itemRect, new Color(255, 255, 0, 0.1f)); - Graphics.DrawFrame(itemRect, new Color(255, 255, 0, 0.2f), 1); - } - } - } - - private void DrawFilledCircleInWorldPosition(Vector3 position, float radius, Color color) - { - var circlePoints = new List(); - const int segments = 15; - const float segmentAngle = 2f * MathF.PI / segments; - - for (var i = 0; i < segments; i++) - { - var angle = i * segmentAngle; - var currentOffset = new Vector2(MathF.Cos(angle), MathF.Sin(angle)) * radius; - var nextOffset = new Vector2(MathF.Cos(angle + segmentAngle), MathF.Sin(angle + segmentAngle)) * radius; - - var currentWorldPos = position + new Vector3(currentOffset, 0); - var nextWorldPos = position + new Vector3(nextOffset, 0); - - circlePoints.Add(GameController.Game.IngameState.Camera.WorldToScreen(currentWorldPos)); - circlePoints.Add(GameController.Game.IngameState.Camera.WorldToScreen(nextWorldPos)); - } - - Graphics.DrawConvexPolyFilled(circlePoints.ToArray(), - color with { A = Color.ToByte((int)((double)0.2f * byte.MaxValue)) }); - Graphics.DrawPolyLine(circlePoints.ToArray(), color, 2); - } -} +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using Beasts.Data; +using Beasts.ExileCore; +using ExileCore.PoEMemory.Components; +using ExileCore.PoEMemory.Elements; +using ExileCore.PoEMemory.Elements.InventoryElements; +using ExileCore.Shared.Enums; +using ExileCore.Shared.Helpers; +using ImGuiNET; +using SharpDX; +using Vector2 = System.Numerics.Vector2; +using Vector3 = System.Numerics.Vector3; + +namespace Beasts; + +public partial class Beasts +{ + private const int TileToGridConversion = 23; + private const int TileToWorldConversion = 250; + private const float GridToWorldMultiplier = TileToWorldConversion / (float)TileToGridConversion; + private const double CameraAngle = 38.7 * Math.PI / 180; + private static readonly float CameraAngleCos = (float)Math.Cos(CameraAngle); + private static readonly float CameraAngleSin = (float)Math.Sin(CameraAngle); + + private double _mapScale; + private SharpDX.RectangleF _rect; + private ImDrawListPtr _backGroundWindowPtr; + + public override void Render() + { + DrawInGameBeasts(); + if (Settings.ShowBeastPricesOnLargeMap.Value) DrawBeastsOnLargeMap(); + if (Settings.ShowBestiaryPanel.Value) DrawBestiaryPanel(); + if (Settings.ShowTrackedBeastsWindow.Value) DrawBeastsWindow(); + if (Settings.ShowCapturedBeastsInInventory.Value) DrawInventoryBeasts(); + if (Settings.ShowCapturedBeastsInStash.Value) DrawStashBeasts(); + } + + private void DrawBeastsOnLargeMap() + { + var ingameUi = GameController.IngameState.IngameUi; + + _rect = GameController.Window.GetWindowRectangle() with { Location = SharpDX.Vector2.Zero }; + if (ingameUi.OpenRightPanel.IsVisible) + { + _rect.Right = ingameUi.OpenRightPanel.GetClientRectCache.Left; + } + + if (ingameUi.OpenLeftPanel.IsVisible) + { + _rect.Left = ingameUi.OpenLeftPanel.GetClientRectCache.Right; + } + + ImGui.SetNextWindowSize(new Vector2(_rect.Width, _rect.Height)); + ImGui.SetNextWindowPos(new Vector2(_rect.Left, _rect.Top)); + + ImGui.Begin("beasts_radar_background", + ImGuiWindowFlags.NoDecoration | + ImGuiWindowFlags.NoInputs | + ImGuiWindowFlags.NoMove | + ImGuiWindowFlags.NoScrollWithMouse | + ImGuiWindowFlags.NoSavedSettings | + ImGuiWindowFlags.NoFocusOnAppearing | + ImGuiWindowFlags.NoBringToFrontOnFocus | + ImGuiWindowFlags.NoBackground); + + // Use foreground draw list so price labels stay above other plugin map icons. + _backGroundWindowPtr = ImGui.GetForegroundDrawList(); + + var map = ingameUi.Map; + var largeMap = map.LargeMap.AsObject(); + if (largeMap.IsVisible) + { + var mapCenter = largeMap.MapCenter; + _mapScale = largeMap.MapScale; + DrawBeastsOnMap(mapCenter); + } + + ImGui.End(); + } + + private void DrawBeastsOnMap(Vector2 mapCenter) + { + var player = GameController.Game.IngameState.Data.LocalPlayer; + var playerRender = player?.GetComponent(); + var playerPositioned = player?.GetComponent(); + if (playerRender == null || playerPositioned == null) return; + + var playerPosition = new Vector2(playerPositioned.GridPosNum.X, playerPositioned.GridPosNum.Y); + var playerHeight = -playerRender.RenderStruct.Height; + var heightData = GameController.IngameState.Data.RawTerrainHeightData; + + foreach (var trackedBeast in _trackedBeasts) + { + var entity = trackedBeast.Value; + var positioned = entity.GetComponent(); + if (positioned == null) continue; + + var beast = BeastsDatabase.AllBeasts.FirstOrDefault(b => entity.Metadata == b.Path); + if (beast == null) continue; + if (Settings.Beasts.All(b => b.Path != beast.Path)) continue; + + var mapPos = EntityToMapPos(positioned, playerPosition, playerHeight, heightData, mapCenter); + + if (Settings.BeastPrices.TryGetValue(beast.DisplayName, out var price) && price > 0) + { + var text = $"{price.ToString(CultureInfo.InvariantCulture)}c"; + var textSize = Graphics.MeasureText(text); + var textOffset = textSize / 2f; + + var bgPadding = new Vector2(4, 2); + var bgColor = new Color(0, 0, 0, 180); + DrawBox(mapPos - textOffset - bgPadding, mapPos + textOffset + bgPadding, bgColor); + + var color = GetSpecialBeastColor(beast.DisplayName); + DrawText(text, mapPos - textOffset, color); + } + } + + // Draw yellow beasts on map + if (Settings.ShowYellowBeasts.Value) + { + foreach (var trackedYellow in _trackedYellowBeasts) + { + var entity = trackedYellow.Value; + var positioned = entity.GetComponent(); + if (positioned == null) continue; + + var mapPos = EntityToMapPos(positioned, playerPosition, playerHeight, heightData, mapCenter); + + var renderName = entity.GetComponent()?.Name ?? "Yellow Beast"; + var text = renderName; + var textSize = Graphics.MeasureText(text); + var textOffset = textSize / 2f; + + var bgPadding = new Vector2(4, 2); + DrawBox(mapPos - textOffset - bgPadding, mapPos + textOffset + bgPadding, new Color(0, 0, 0, 180)); + DrawText(text, mapPos - textOffset, new Color(255, 250, 0)); + } + } + } + + private Vector2 EntityToMapPos(Positioned positioned, Vector2 playerPosition, float playerHeight, float[][] heightData, Vector2 mapCenter) + { + var beastPosition = new Vector2(positioned.GridPosNum.X, positioned.GridPosNum.Y); + var beastGridPos = positioned.GridPosNum; + + float beastHeight = 0; + int beastX = (int)beastGridPos.X; + int beastY = (int)beastGridPos.Y; + if (heightData != null && beastY >= 0 && beastY < heightData.Length + && beastX >= 0 && beastX < heightData[beastY].Length) + { + beastHeight = heightData[beastY][beastX]; + } + + var mapDelta = TranslateGridDeltaToMapDelta(beastPosition - playerPosition, playerHeight + beastHeight); + return mapCenter + mapDelta; + } + + private Vector2 TranslateGridDeltaToMapDelta(Vector2 delta, float deltaZ) + { + deltaZ /= GridToWorldMultiplier; + return (float)_mapScale * new Vector2((delta.X - delta.Y) * CameraAngleCos, + (deltaZ - (delta.X + delta.Y)) * CameraAngleSin); + } + + private void DrawBox(Vector2 p0, Vector2 p1, Color color) + { + _backGroundWindowPtr.AddRectFilled(p0, p1, + ImGui.ColorConvertFloat4ToU32(new System.Numerics.Vector4(color.R / 255f, color.G / 255f, + color.B / 255f, color.A / 255f))); + } + + private void DrawText(string text, Vector2 pos, Color color) + { + _backGroundWindowPtr.AddText(pos, + ImGui.ColorConvertFloat4ToU32(new System.Numerics.Vector4(color.R / 255f, color.G / 255f, + color.B / 255f, color.A / 255f)), text); + } + + private void DrawInGameBeasts() + { + foreach (var trackedBeast in _trackedBeasts + .Select(beast => new { Positioned = beast.Value.GetComponent(), beast.Value.Metadata }) + .Where(beast => beast.Positioned != null)) + { + var beast = BeastsDatabase.AllBeasts.First(beast => trackedBeast.Metadata == beast.Path); + + if (Settings.Beasts.All(b => b.Path != beast.Path)) continue; + var pos = GameController.IngameState.Data.ToWorldWithTerrainHeight(trackedBeast.Positioned.GridPosition); + Graphics.DrawText(beast.DisplayName, GameController.IngameState.Camera.WorldToScreen(pos), Color.White, + FontAlign.Center); + + DrawFilledCircleInWorldPosition(pos, 100, GetSpecialBeastColor(beast.DisplayName)); + } + + // Draw yellow beasts in world + if (Settings.ShowYellowBeasts.Value) + { + foreach (var trackedYellow in _trackedYellowBeasts) + { + var entity = trackedYellow.Value; + var positioned = entity.GetComponent(); + if (positioned == null) continue; + + var renderName = entity.GetComponent()?.Name ?? "Yellow Beast"; + var pos = GameController.IngameState.Data.ToWorldWithTerrainHeight(positioned.GridPosition); + Graphics.DrawText(renderName, GameController.IngameState.Camera.WorldToScreen(pos), new Color(255, 250, 0), + FontAlign.Center); + + DrawFilledCircleInWorldPosition(pos, 100, new Color(255, 250, 0)); + } + } + } + + private static Color GetSpecialBeastColor(string beastName) + { + if (beastName.Contains("Vivid")) + { + return new Color(255, 250, 0); + } + + if (beastName.Contains("Wild")) + { + return new Color(255, 0, 235); + } + + if (beastName.Contains("Primal")) + { + return new Color(0, 245, 255); + } + + if (beastName.Contains("Black")) + { + return new Color(255, 255, 255); + } + + return Color.Red; + } + + private void DrawBestiaryPanel() + { + var bestiary = GameController.IngameState.IngameUi.GetBestiaryPanel(); + if (bestiary == null || bestiary.IsVisible == false) return; + + var capturedBeastsPanel = bestiary.CapturedBeastsPanel; + if (capturedBeastsPanel == null || capturedBeastsPanel.IsVisible == false) return; + + var beasts = bestiary.CapturedBeastsPanel.CapturedBeasts; + foreach (var beast in beasts) + { + try + { + var beastMetadata = Settings.Beasts.Find(b => b.DisplayName == beast.DisplayName); + if (beastMetadata == null) continue; + if (!Settings.BeastPrices.ContainsKey(beastMetadata.DisplayName)) continue; + + var center = new Vector2(beast.GetClientRect().Center.X, beast.GetClientRect().Center.Y); + + Graphics.DrawBox(beast.GetClientRect(), new Color(0, 0, 0, 0.5f)); + Graphics.DrawFrame(beast.GetClientRect(), Color.White, 2); + Graphics.DrawText(beastMetadata.DisplayName, center, Color.White, FontAlign.Center); + + var text = Settings.BeastPrices[beastMetadata.DisplayName].ToString(CultureInfo.InvariantCulture) + "c"; + var textPos = center + new Vector2(0, 20); + Graphics.DrawText(text, textPos, Color.White, FontAlign.Center); + } + catch (Exception) + { + // ignored + } + } + } + + private void DrawBeastsWindow() + { + ImGui.SetNextWindowSize(new Vector2(0, 0)); + ImGui.SetNextWindowBgAlpha(0.6f); + ImGui.Begin("Beasts Window", ImGuiWindowFlags.NoDecoration); + + if (ImGui.BeginTable("Beasts Table", 2, + ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersOuter | ImGuiTableFlags.BordersV)) + { + ImGui.TableSetupColumn("Price", ImGuiTableColumnFlags.WidthFixed, 48); + ImGui.TableSetupColumn("Beast"); + + foreach (var beastMetadata in _trackedBeasts + .Select(trackedBeast => trackedBeast.Value) + .Select(beast => Settings.Beasts.Find(b => b.Path == beast.Metadata)) + .Where(beastMetadata => beastMetadata != null)) + { + ImGui.TableNextRow(); + + ImGui.TableNextColumn(); + + ImGui.Text(Settings.BeastPrices.TryGetValue(beastMetadata.DisplayName, out var price) + ? $"{price.ToString(CultureInfo.InvariantCulture)}c" + : "0c"); + + ImGui.TableNextColumn(); + + ImGui.Text(beastMetadata.DisplayName); + foreach (var craft in beastMetadata.Crafts) + { + ImGui.Text(craft); + } + } + + // Yellow beasts in tracking window + if (Settings.ShowYellowBeasts.Value) + { + foreach (var trackedYellow in _trackedYellowBeasts) + { + var entity = trackedYellow.Value; + var renderName = entity.GetComponent()?.Name ?? "Yellow Beast"; + + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + ImGui.TextColored(new System.Numerics.Vector4(1f, 0.98f, 0f, 1f), "-"); + ImGui.TableNextColumn(); + ImGui.TextColored(new System.Numerics.Vector4(1f, 0.98f, 0f, 1f), renderName); + } + } + + ImGui.EndTable(); + } + + ImGui.End(); + } + + private void DrawInventoryBeasts() + { + var inventory = GameController.Game.IngameState.IngameUi.InventoryPanel[InventoryIndex.PlayerInventory]; + if (!inventory.IsVisible) return; + + DrawCapturedBeasts(inventory.VisibleInventoryItems); + } + + private void DrawStashBeasts() + { + var stash = GameController.Game.IngameState.IngameUi.StashElement; + if (stash == null || !stash.IsVisible) return; + + var visibleStash = stash.VisibleStash; + if (visibleStash == null) return; + + var items = visibleStash.VisibleInventoryItems; + if (items == null) return; + + DrawCapturedBeasts(items); + } + + private void DrawCapturedBeasts(IList items) + { + if (items == null || items.Count == 0) return; + + foreach (var item in items) + { + if (item?.Item == null) continue; + if (item.Item.Metadata != "Metadata/Items/Currency/CurrencyItemisedCapturedMonster") continue; + + var itemRect = item.GetClientRect(); + var monster = item.Item.GetComponent(); + var monsterName = monster?.MonsterVariety?.MonsterName; + + if (!string.IsNullOrEmpty(monsterName) && Settings.BeastPrices.TryGetValue(monsterName, out var price)) + { + Graphics.DrawBox(itemRect, new Color(0, 0, 0, 0.1f)); + Graphics.DrawText($"{price.ToString(CultureInfo.InvariantCulture)}c", itemRect.Center, + Color.White, FontAlign.Center); + } + else + { + Graphics.DrawBox(itemRect, new Color(255, 255, 0, 0.1f)); + Graphics.DrawFrame(itemRect, new Color(255, 255, 0, 0.2f), 1); + } + } + } + + private void DrawFilledCircleInWorldPosition(Vector3 position, float radius, Color color) + { + var circlePoints = new List(); + const int segments = 15; + const float segmentAngle = 2f * MathF.PI / segments; + + for (var i = 0; i < segments; i++) + { + var angle = i * segmentAngle; + var currentOffset = new Vector2(MathF.Cos(angle), MathF.Sin(angle)) * radius; + var nextOffset = new Vector2(MathF.Cos(angle + segmentAngle), MathF.Sin(angle + segmentAngle)) * radius; + + var currentWorldPos = position + new Vector3(currentOffset, 0); + var nextWorldPos = position + new Vector3(nextOffset, 0); + + circlePoints.Add(GameController.Game.IngameState.Camera.WorldToScreen(currentWorldPos)); + circlePoints.Add(GameController.Game.IngameState.Camera.WorldToScreen(nextWorldPos)); + } + + Graphics.DrawConvexPolyFilled(circlePoints.ToArray(), + color with { A = Color.ToByte((int)((double)0.2f * byte.MaxValue)) }); + Graphics.DrawPolyLine(circlePoints.ToArray(), color, 2); + } +} \ No newline at end of file diff --git a/BeastsSettings.cs b/BeastsSettings.cs index 9a37f79..3010cf8 100755 --- a/BeastsSettings.cs +++ b/BeastsSettings.cs @@ -1,146 +1,148 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Beasts.Data; -using ExileCore.Shared.Helpers; -using ExileCore.Shared.Interfaces; -using ExileCore.Shared.Nodes; -using ImGuiNET; -using Newtonsoft.Json; -using SharpDX; - -namespace Beasts; - -public class BeastsSettings : ISettings -{ - public List Beasts { get; set; } = new(); - public Dictionary BeastPrices { get; set; } = new(); - public DateTime LastUpdate { get; set; } = DateTime.MinValue; - - public BeastsSettings() - { - BeastPicker = new CustomNode - { - DrawDelegate = () => - { - ImGui.Separator(); - if (ImGui.BeginTable("BeastsTable", 4, - ImGuiTableFlags.Resizable | ImGuiTableFlags.Reorderable | ImGuiTableFlags.Sortable | - ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersOuter | ImGuiTableFlags.BordersV | - ImGuiTableFlags.NoBordersInBody | ImGuiTableFlags.ScrollY)) - { - ImGui.TableSetupColumn("Enabled", ImGuiTableColumnFlags.WidthFixed, 24); - ImGui.TableSetupColumn("Price", ImGuiTableColumnFlags.WidthFixed, 48); - ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, 256); - ImGui.TableSetupColumn("Description", ImGuiTableColumnFlags.WidthStretch); - ImGui.TableSetupScrollFreeze(0, 1); - ImGui.TableHeadersRow(); - - var sortedBeasts = BeastsDatabase.AllBeasts; - if (ImGui.TableGetSortSpecs() is { SpecsDirty: true } sortSpecs) - { - int sortedColumn = sortSpecs.Specs.ColumnIndex; - var sortAscending = sortSpecs.Specs.SortDirection == ImGuiSortDirection.Ascending; - - sortedBeasts = sortedColumn switch - { - 0 => sortAscending - ? [.. sortedBeasts.OrderBy(b => Beasts.Any(eb => eb.Path == b.Path))] - : [.. sortedBeasts.OrderByDescending(b => Beasts.Any(eb => eb.Path == b.Path))], - 1 => sortAscending - ? [.. sortedBeasts.OrderBy(b => BeastPrices[b.DisplayName])] - : [.. sortedBeasts.OrderByDescending(b => BeastPrices[b.DisplayName])], - 2 => sortAscending - ? [.. sortedBeasts.OrderBy(b => b.DisplayName)] - : [.. sortedBeasts.OrderByDescending(x => x.DisplayName)], - 3 => sortAscending - ? [.. sortedBeasts.OrderBy(b => b.Crafts[0])] - : [.. sortedBeasts.OrderByDescending(x => x.Crafts[0])], - _ => sortAscending - ? [.. sortedBeasts.OrderBy(b => b.DisplayName)] - : [.. sortedBeasts.OrderByDescending(x => x.DisplayName)] - }; - } - - foreach (var beast in sortedBeasts) - { - ImGui.TableNextRow(); - ImGui.TableNextColumn(); - - var isChecked = Beasts.Any(eb => eb.Path == beast.Path); - if (ImGui.Checkbox($"##{beast.Path}", ref isChecked)) - { - if (isChecked) - { - Beasts.Add(beast); - } - else - { - Beasts.RemoveAll(eb => eb.Path == beast.Path); - } - } - - if (isChecked) - { - ImGui.PushStyleColor(ImGuiCol.Text, Color.Green.ToImguiVec4()); - } - - ImGui.TableNextColumn(); - ImGui.Text(BeastPrices.TryGetValue(beast.DisplayName, out var price) ? $"{price}c" : "0c"); - - ImGui.TableNextColumn(); - ImGui.Text(beast.DisplayName); - - ImGui.TableNextColumn(); - // display all the crafts for the beast seperated by newline - foreach (var craft in beast.Crafts) - { - ImGui.Text(craft); - } - - if (isChecked) - { - ImGui.PopStyleColor(); - } - - ImGui.NextColumn(); - } - - ImGui.EndTable(); - } - } - }; - - LastUpdated = new CustomNode - { - DrawDelegate = () => - { - ImGui.Text("PoeNinja prices as of:"); - ImGui.SameLine(); - ImGui.Text(LastUpdate.ToString("HH:mm:ss")); - } - }; - } - - public ToggleNode Enable { get; set; } = new ToggleNode(false); - - public ToggleNode ShowTrackedBeastsWindow { get; set; } = new ToggleNode(true); - - public ToggleNode ShowBeastPricesOnLargeMap { get; set; } = new ToggleNode(true); - - public ToggleNode ShowCapturedBeastsInInventory { get; set; } = new ToggleNode(true); - - public ToggleNode ShowCapturedBeastsInStash { get; set; } = new ToggleNode(true); - - public ToggleNode ShowBestiaryPanel { get; set; } = new ToggleNode(true); - - public ToggleNode AutoRefreshPrices { get; set; } = new ToggleNode(true); - - public RangeNode PriceRefreshMinutes { get; set; } = new(15, 1, 60); - - public ButtonNode FetchBeastPrices { get; set; } = new ButtonNode(); - - [JsonIgnore] public CustomNode LastUpdated { get; set; } - - [JsonIgnore] public CustomNode BeastPicker { get; set; } +using System; +using System.Collections.Generic; +using System.Linq; +using Beasts.Data; +using ExileCore.Shared.Helpers; +using ExileCore.Shared.Interfaces; +using ExileCore.Shared.Nodes; +using ImGuiNET; +using Newtonsoft.Json; +using SharpDX; + +namespace Beasts; + +public class BeastsSettings : ISettings +{ + public List Beasts { get; set; } = new(); + public Dictionary BeastPrices { get; set; } = new(); + public DateTime LastUpdate { get; set; } = DateTime.MinValue; + + public BeastsSettings() + { + BeastPicker = new CustomNode + { + DrawDelegate = () => + { + ImGui.Separator(); + if (ImGui.BeginTable("BeastsTable", 4, + ImGuiTableFlags.Resizable | ImGuiTableFlags.Reorderable | ImGuiTableFlags.Sortable | + ImGuiTableFlags.RowBg | ImGuiTableFlags.BordersOuter | ImGuiTableFlags.BordersV | + ImGuiTableFlags.NoBordersInBody | ImGuiTableFlags.ScrollY)) + { + ImGui.TableSetupColumn("Enabled", ImGuiTableColumnFlags.WidthFixed, 24); + ImGui.TableSetupColumn("Price", ImGuiTableColumnFlags.WidthFixed, 48); + ImGui.TableSetupColumn("Name", ImGuiTableColumnFlags.WidthFixed, 256); + ImGui.TableSetupColumn("Description", ImGuiTableColumnFlags.WidthStretch); + ImGui.TableSetupScrollFreeze(0, 1); + ImGui.TableHeadersRow(); + + var sortedBeasts = BeastsDatabase.AllBeasts; + if (ImGui.TableGetSortSpecs() is { SpecsDirty: true } sortSpecs) + { + int sortedColumn = sortSpecs.Specs.ColumnIndex; + var sortAscending = sortSpecs.Specs.SortDirection == ImGuiSortDirection.Ascending; + + sortedBeasts = sortedColumn switch + { + 0 => sortAscending + ? [.. sortedBeasts.OrderBy(b => Beasts.Any(eb => eb.Path == b.Path))] + : [.. sortedBeasts.OrderByDescending(b => Beasts.Any(eb => eb.Path == b.Path))], + 1 => sortAscending + ? [.. sortedBeasts.OrderBy(b => BeastPrices[b.DisplayName])] + : [.. sortedBeasts.OrderByDescending(b => BeastPrices[b.DisplayName])], + 2 => sortAscending + ? [.. sortedBeasts.OrderBy(b => b.DisplayName)] + : [.. sortedBeasts.OrderByDescending(x => x.DisplayName)], + 3 => sortAscending + ? [.. sortedBeasts.OrderBy(b => b.Crafts[0])] + : [.. sortedBeasts.OrderByDescending(x => x.Crafts[0])], + _ => sortAscending + ? [.. sortedBeasts.OrderBy(b => b.DisplayName)] + : [.. sortedBeasts.OrderByDescending(x => x.DisplayName)] + }; + } + + foreach (var beast in sortedBeasts) + { + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + + var isChecked = Beasts.Any(eb => eb.Path == beast.Path); + if (ImGui.Checkbox($"##{beast.Path}", ref isChecked)) + { + if (isChecked) + { + Beasts.Add(beast); + } + else + { + Beasts.RemoveAll(eb => eb.Path == beast.Path); + } + } + + if (isChecked) + { + ImGui.PushStyleColor(ImGuiCol.Text, Color.Green.ToImguiVec4()); + } + + ImGui.TableNextColumn(); + ImGui.Text(BeastPrices.TryGetValue(beast.DisplayName, out var price) ? $"{price}c" : "0c"); + + ImGui.TableNextColumn(); + ImGui.Text(beast.DisplayName); + + ImGui.TableNextColumn(); + // display all the crafts for the beast seperated by newline + foreach (var craft in beast.Crafts) + { + ImGui.Text(craft); + } + + if (isChecked) + { + ImGui.PopStyleColor(); + } + + ImGui.NextColumn(); + } + + ImGui.EndTable(); + } + } + }; + + LastUpdated = new CustomNode + { + DrawDelegate = () => + { + ImGui.Text("PoeNinja prices as of:"); + ImGui.SameLine(); + ImGui.Text(LastUpdate.ToString("HH:mm:ss")); + } + }; + } + + public ToggleNode Enable { get; set; } = new ToggleNode(false); + + public ToggleNode ShowTrackedBeastsWindow { get; set; } = new ToggleNode(true); + + public ToggleNode ShowYellowBeasts { get; set; } = new ToggleNode(false); + + public ToggleNode ShowBeastPricesOnLargeMap { get; set; } = new ToggleNode(true); + + public ToggleNode ShowCapturedBeastsInInventory { get; set; } = new ToggleNode(true); + + public ToggleNode ShowCapturedBeastsInStash { get; set; } = new ToggleNode(true); + + public ToggleNode ShowBestiaryPanel { get; set; } = new ToggleNode(true); + + public ToggleNode AutoRefreshPrices { get; set; } = new ToggleNode(true); + + public RangeNode PriceRefreshMinutes { get; set; } = new(15, 1, 60); + + public ButtonNode FetchBeastPrices { get; set; } = new ButtonNode(); + + [JsonIgnore] public CustomNode LastUpdated { get; set; } + + [JsonIgnore] public CustomNode BeastPicker { get; set; } } \ No newline at end of file