Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Add a hotkey to enable price tooltip #18

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

mattpsvreis
Copy link

@mattpsvreis mattpsvreis commented Oct 26, 2024

As described in #5 and #11, the game stutters heavily when playing the multiplayer version of SPT, FIKA, more evident with weapons which has a bunch of mods that generates a bunch of calls to the server causing a considerable freeze on the game if you're also playing with people overseas with over a hundred ping, sometimes it being 5 seconds freezes during raids or whatnot (my case). This is very bad and I understand you're looking into a way of fixing this - a price caching approach isn't that bad but for now we really need a band-aid fix to at least put it at bay and have us control when we want the game to actually freeze to check the flea market prices through a hotkey.

In the PR #8, this hotkey was added but it wasn't merged in for some reason and the code got stale and needed to be updated. I went ahead and fixed the conflicts myself through this fork and urge for this to be merged at your earliest convenience.

Furthermore, I'll make a suggestion of how I'd approach the fetching based on my developer knowledge. I'm not that knowledgeable with SPT/FIKA/EFT coding so bear with me:

private static async Task PrefixAsync(ref string text, ref float delay, SimpleTooltip __instance)
{
    bool isFleaEligible = false;
    double lowestFleaOffer = 0;

    bool modifierKeyHeld = Input.GetKey((KeyCode)LootValueMod.showPriceKey.Value) || LootValueMod.showPriceKey.Value == 0;
    bool inRaidAndCanShowInRaid = HasRaidStarted() && LootValueMod.showFleaPricesInRaid.Value;

    // Early exit if conditions aren't met
    if (hoveredItem == null || !Session.Profile.Examined(hoveredItem) || !LootValueMod.showPrices.Value || (!HasRaidStarted() && !inRaidAndCanShowInRaid) || !modifierKeyHeld)
    {
        return;
    }

    delay = 0; // Show tooltip immediately if showing price
    tooltip = __instance;

    TraderOffer bestTraderOffer = GetBestTraderOffer(hoveredItem);
    int fleaPricePerSlot = 0, traderPricePerSlot = 0;

    // Fetch flea prices asynchronously
    if (hoveredItem is Weapon weapon)
    {
        double totalFleaPrice = await FetchWeaponModsFleaPrices(weapon);

        if (totalFleaPrice > 0)
        {
            isFleaEligible = true;
            lowestFleaOffer = totalFleaPrice;
        }
    }
    else
    {
        double? fleaPrice = await FleaPriceCache.FetchPriceAsync(hoveredItem.TemplateId);

        if (fleaPrice.HasValue)
        {
            isFleaEligible = true;
            lowestFleaOffer = fleaPrice.Value * hoveredItem.StackObjectsCount;
        }
    }

    // Calculate prices per slot and set text
    var size = hoveredItem.CalculateCellSize();
    int slots = size.X * size.Y;

    if (isFleaEligible)
        fleaPricePerSlot = (int)Math.Round(lowestFleaOffer / slots);

    if (bestTraderOffer != null)
    {
        double totalTraderPrice = bestTraderOffer.Price;
        traderPricePerSlot = (int)Math.Round(totalTraderPrice / slots);
        SetText(traderPricePerSlot, fleaPricePerSlot, totalTraderPrice, slots, ref text, bestTraderOffer.TraderName);
    }

    if (isFleaEligible)
        SetText(fleaPricePerSlot, traderPricePerSlot, lowestFleaOffer, slots, ref text, "Flea");
}

private static async Task<double> FetchWeaponModsFleaPrices(Weapon weapon)
{
    double totalFleaPrice = 0;

    // Create tasks for each mod's flea price fetching
    List<Task<double?>> priceTasks = new();
    foreach (Mod mod in weapon.Mods)
    {
        priceTasks.Add(FleaPriceCache.FetchPriceAsync(mod.TemplateId));
    }

    // Await all tasks simultaneously
    double?[] prices = await Task.WhenAll(priceTasks);

    for (int i = 0; i < prices.Length; i++)
    {
        if (prices[i].HasValue)
        {
            totalFleaPrice += prices[i].Value * weapon.Mods[i].StackObjectsCount;
        }
    }

    return totalFleaPrice;
}

What key improvements I suggest are:

  1. Asynchronous Price Fetching: Using Task.WhenAll in FetchWeaponModsFleaPrices allows all flea price requests to run concurrently.
  2. Reduced Blocking with await: No .Result calls prevent blocking the main thread, allowing smoother gameplay.
  3. Early Exit: Conditions are checked upfront, exiting early if prices shouldn’t be shown.

Obviously this depends on adaptation to your mod and some tweaks here and there for actual usage - but this is what I could think of in my current knowledge.

@mattpsvreis
Copy link
Author

@IhanaMies

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants