Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 70 additions & 2 deletions Ninja Price/Main/CustomItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,70 @@ public class CurrencyData
public int MaxStackSize = 0;
}

private static bool IsLikelyMapItem(string path, string className, string baseName)
{
if (string.IsNullOrEmpty(path))
{
return false;
}

if (path.Contains("MapKey", StringComparison.OrdinalIgnoreCase) ||
path.StartsWith("Metadata/Items/Maps/", StringComparison.Ordinal))
{
return true;
}

if (!string.IsNullOrEmpty(className) &&
className.Contains("Map", StringComparison.OrdinalIgnoreCase) &&
!className.Contains("Fragment", StringComparison.OrdinalIgnoreCase) &&
!className.Contains("MiscMapItem", StringComparison.OrdinalIgnoreCase))
{
return true;
}

return !string.IsNullOrEmpty(baseName) && baseName.Contains("Map", StringComparison.OrdinalIgnoreCase);
}

private static int GetFallbackMapTier(string path, string baseName)
{
var tierFromPath = ExtractTrailingNumber(path, "MapKeyTier");
if (tierFromPath > 0)
{
return tierFromPath;
}

var tierFromName = ExtractTrailingNumber(baseName, "(Tier ");
if (tierFromName > 0)
{
return tierFromName;
}

return 0;
}

private static int ExtractTrailingNumber(string value, string token)
{
if (string.IsNullOrEmpty(value))
{
return 0;
}

var tokenIndex = value.IndexOf(token, StringComparison.OrdinalIgnoreCase);
if (tokenIndex < 0)
{
return 0;
}

var numberStart = tokenIndex + token.Length;
var numberEnd = numberStart;
while (numberEnd < value.Length && char.IsDigit(value[numberEnd]))
{
numberEnd++;
}

return numberEnd > numberStart && int.TryParse(value[numberStart..numberEnd], out var number) ? number : 0;
}

public CustomItem()
{
}
Expand Down Expand Up @@ -220,8 +284,12 @@ public CustomItem(Entity itemEntity, Element element)
if (weaponClass.Any(ClassName.Equals))
IsWeapon = true;

MapInfo.MapTier = itemEntity.TryGetComponent<MapKey>(out var map) ? map.Tier : 0;
MapInfo.IsMap = MapInfo.MapTier > 0;
MapInfo.MapTier = GetFallbackMapTier(Path, BaseName);
MapInfo.IsMap = MapInfo.MapTier > 0 || IsLikelyMapItem(Path, ClassName, BaseName);
if (MapInfo.IsMap && MapInfo.MapTier == 0)
{
MapInfo.MapTier = 1;
}

if (Rarity != ItemRarity.Unique && MapInfo.IsMap)
{
Expand Down
8 changes: 7 additions & 1 deletion Ninja Price/Main/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public override bool Initialise()
Directory.CreateDirectory(NinjaDirectory);

UpdateLeagueList();
SyncCurrentLeague();
StartDataReload(Settings.DataSourceSettings.League.Value, false);

Settings.DataSourceSettings.ReloadPrices.OnPressed += () => StartDataReload(Settings.DataSourceSettings.League.Value, true);
Expand Down Expand Up @@ -215,7 +216,12 @@ private void UpdateLeagueList()
{
var leagueListFromUrl = Utils.DownloadFromUrl("https://poe.ninja/poe1/api/data/index-state").Result;
var leagueData = JsonConvert.DeserializeObject<NinjaLeagueListRootObject>(leagueListFromUrl);
leagueList.UnionWith(leagueData.economyLeagues.Where(league => league.indexed).Select(league => league.name));
if (leagueData?.economyLeagues != null)
{
leagueList.UnionWith(leagueData.economyLeagues
.Select(league => league.name)
.Where(name => !string.IsNullOrWhiteSpace(name)));
}
}
catch (Exception ex)
{
Expand Down
153 changes: 122 additions & 31 deletions Ninja Price/Main/Render.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using ImGuiNET;
using Ninja_Price.Enums;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
Expand Down Expand Up @@ -55,6 +56,35 @@ public Main()
_disenchantCache = new TimeCache<List<VillageUniqueDisenchantValue>>(() => GameController.Files.VillageUniqueDisenchantValues.EntriesList, 1000);
}

private object GetOptionalIngameUiWindow(string propertyName)
{
var ingameUi = GameController?.Game?.IngameState?.IngameUi;
return ingameUi?.GetType().GetProperty(propertyName)?.GetValue(ingameUi);
}

private static bool IsWindowVisible(object window)
{
return window?.GetType().GetProperty("IsVisible")?.GetValue(window) is bool isVisible && isVisible;
}

private List<NormalInventoryItem> GetTrappedStashItems()
{
var trappedStashWindow = GetOptionalIngameUiWindow("TrappedStashWindow");
if (!IsWindowVisible(trappedStashWindow))
{
return [];
}

return trappedStashWindow?.GetType().GetProperty("Items")?.GetValue(trappedStashWindow) is IEnumerable items
? items.OfType<NormalInventoryItem>().ToList()
: [];
}

private bool IsTrappedStashVisible()
{
return IsWindowVisible(GetOptionalIngameUiWindow("TrappedStashWindow"));
}

private List<ItemOnGround> GetItemsOnGround(List<ItemOnGround> previousValue)
{
var prevDict = previousValue
Expand Down Expand Up @@ -110,6 +140,8 @@ private List<ItemOnGround> GetItemsOnGroundSlow()

public override void Render()
{
SyncCurrentLeague();

#region Reset All Data

StashTabValue = 0;
Expand Down Expand Up @@ -167,8 +199,8 @@ public override void Render()
{
ItemList = ritualItems;
}
if (Settings.LeagueSpecificSettings.ShowTrappedStashPrices &&
GameController.Game.IngameState.IngameUi.TrappedStashWindow is { IsVisible: true, Items: { Count: > 0 } trappedStashItems })
var trappedStashItems = Settings.LeagueSpecificSettings.ShowTrappedStashPrices ? GetTrappedStashItems() : [];
if (trappedStashItems.Count > 0)
{
ItemList = trappedStashItems;
}
Expand Down Expand Up @@ -281,7 +313,7 @@ public void DrawGraphics()
}
}
else if (
Settings.LeagueSpecificSettings.ShowTrappedStashPrices && GameController.IngameState.IngameUi.TrappedStashWindow.IsVisible ||
Settings.LeagueSpecificSettings.ShowTrappedStashPrices && IsTrappedStashVisible() ||
Settings.LeagueSpecificSettings.ShowRitualWindowPrices && GameController.IngameState.IngameUi.RitualWindow.IsVisible ||
Settings.LeagueSpecificSettings.ShowVillageRewardWindowPrices && GameController.IngameState.IngameUi.VillageRewardWindow.IsVisible ||
Settings.LeagueSpecificSettings.ShowMercenaryInventoryPrices && GameController.IngameState.IngameUi.MercenaryEncounterWindow.IsVisible ||
Expand Down Expand Up @@ -380,6 +412,90 @@ private void DrawItemPriceInline(CustomItem customItem)
textColor, FontAlign.Center, backgroundColor);
}

private string GetMatchingCustomSoundFile(CustomItem item)
{
return item.UniqueNameCandidates.Any() || !string.IsNullOrEmpty(item.UniqueName)
? item.UniqueNameCandidates
.DefaultIfEmpty(item.UniqueName)
.Select(x => _soundFiles.GetValueOrDefault(x))
.FirstOrDefault(x => x != null)
: null;
}

private bool ShouldPlaySoundForItem(CustomItem item, string matchingCustomFile)
{
if (!Settings.SoundNotificationSettings.Enabled || !IsSoundCategoryEnabled(item))
{
return false;
}

return item.PriceData.MaxChaosValue >= Settings.SoundNotificationSettings.ValueThreshold.Value ||
Settings.SoundNotificationSettings.PlayCustomSoundsIfBelowThreshold && matchingCustomFile != null;
}

private bool IsSoundCategoryEnabled(CustomItem item)
{
return item.ItemType switch
{
ItemTypes.UniqueAccessory or
ItemTypes.UniqueArmour or
ItemTypes.UniqueFlask or
ItemTypes.UniqueJewel or
ItemTypes.UniqueMap or
ItemTypes.UniqueWeapon => Settings.SoundNotificationSettings.AlertForUniques,

ItemTypes.Currency or
ItemTypes.DjinnCoin or
ItemTypes.Wombgift or
ItemTypes.Catalyst or
ItemTypes.Artifact or
ItemTypes.Oil or
ItemTypes.Tattoo or
ItemTypes.Omen or
ItemTypes.Resonator or
ItemTypes.Fossil or
ItemTypes.Incubator or
ItemTypes.DeliriumOrbs or
ItemTypes.Vials or
ItemTypes.KalguuranRune or
ItemTypes.AllflameEmber => Settings.SoundNotificationSettings.AlertForCurrency,

ItemTypes.Fragment or
ItemTypes.Scarab or
ItemTypes.Invitation or
ItemTypes.InscribedUltimatum => Settings.SoundNotificationSettings.AlertForFragments,

ItemTypes.Map => Settings.SoundNotificationSettings.AlertForMaps,
ItemTypes.DivinationCard => Settings.SoundNotificationSettings.AlertForDivinationCards,
ItemTypes.Essence => Settings.SoundNotificationSettings.AlertForEssences,
ItemTypes.SkillGem or
ItemTypes.ClusterJewel => Settings.SoundNotificationSettings.AlertForGemsAndJewels,
ItemTypes.Beast => Settings.SoundNotificationSettings.AlertForBeasts,
_ => Settings.SoundNotificationSettings.AlertForOtherTypes
};
}

private void PlaySoundAlert(string matchingCustomFile)
{
var defaultFile = Path.Join(ConfigDirectory, Main.DefaultWav);
if (matchingCustomFile != null && !File.Exists(matchingCustomFile))
{
LogError($"Unable to find {matchingCustomFile}. It was probably deleted. Reload the sound list to update your preferences");
matchingCustomFile = null;
}

var fileToPlay = matchingCustomFile ?? defaultFile;
if (File.Exists(fileToPlay))
{
GameController.SoundController.PlaySound(fileToPlay, Settings.SoundNotificationSettings.Volume);
}
else if (fileToPlay == defaultFile)
{
LogError(
$"Unable to find the default sound file ({defaultFile}) to play. Disable the sound notification feature, reload the sound list to let the plugin create it, or create it yourself");
}
}

private void ProcessHoveredItem()
{
if (!Settings.HoveredItemSettings.Show) return;
Expand Down Expand Up @@ -987,37 +1103,12 @@ private void ProcessItemsOnGround()
if (Settings.SoundNotificationSettings.Enabled &&
!_soundPlayedTracker.ContainsKey(item.EntityId))
{
var matchingCustomFile =
item.UniqueNameCandidates.Any() ||
!string.IsNullOrEmpty(item.UniqueName)
? item.UniqueNameCandidates
.DefaultIfEmpty(item.UniqueName)
.Select(x => _soundFiles.GetValueOrDefault(x))
.FirstOrDefault(x => x != null)
: null;
if (item.PriceData.MaxChaosValue >= Settings.SoundNotificationSettings.ValueThreshold ||
Settings.SoundNotificationSettings.PlayCustomSoundsIfBelowThreshold && matchingCustomFile != null)
var matchingCustomFile = GetMatchingCustomSoundFile(item);
if (ShouldPlaySoundForItem(item, matchingCustomFile))
{
if (_soundPlayedTracker.TryAdd(item.EntityId, true))
{
var defaultFile = Path.Join(ConfigDirectory, "default.wav");
if (matchingCustomFile != null && !File.Exists(matchingCustomFile))
{
LogError($"Unable to find {matchingCustomFile}. It was probably deleted. Reload the sound list to update your preferences");
matchingCustomFile = null;
}

var fileToPlay = matchingCustomFile ?? defaultFile;

if (File.Exists(fileToPlay))
{
GameController.SoundController.PlaySound(fileToPlay, Settings.SoundNotificationSettings.Volume);
}
else if (fileToPlay == defaultFile)
{
LogError(
$"Unable to find the default sound file ({defaultFile}) to play. Disable the sound notification feature, reload the sound list to let the plugin create it, or create it yourself");
}
PlaySoundAlert(matchingCustomFile);
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions Ninja Price/Settings/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,13 @@ public class SoundNotificationSettings
public RangeNode<float> Volume { get; set; } = new(1, 0, 2);
public RangeNode<int> ValueThreshold { get; set; } = new(50, 0, 100000);
public ToggleNode PlayCustomSoundsIfBelowThreshold { get; set; } = new ToggleNode(true);
public ToggleNode AlertForUniques { get; set; } = new ToggleNode(true);
public ToggleNode AlertForCurrency { get; set; } = new ToggleNode(true);
public ToggleNode AlertForFragments { get; set; } = new ToggleNode(true);
public ToggleNode AlertForMaps { get; set; } = new ToggleNode(true);
public ToggleNode AlertForDivinationCards { get; set; } = new ToggleNode(true);
public ToggleNode AlertForEssences { get; set; } = new ToggleNode(true);
public ToggleNode AlertForGemsAndJewels { get; set; } = new ToggleNode(true);
public ToggleNode AlertForBeasts { get; set; } = new ToggleNode(true);
public ToggleNode AlertForOtherTypes { get; set; } = new ToggleNode(true);
}