From 93ca364fdbad5315864bd6ddb96f5a1c784756a8 Mon Sep 17 00:00:00 2001 From: Daniel Urbanski Date: Sat, 15 Jan 2022 17:26:51 -0800 Subject: [PATCH] Add splitscreen support, improver error handling, fix NPC issue with henchman --- .../BetterFriendship/BubbleDrawer.cs | 50 ++++++++--------- .../BetterFriendship/GameExtensions.cs | 5 +- BetterFriendship/BetterFriendship/ModEntry.cs | 53 +++++++++++++++---- .../BetterFriendship/manifest.json | 2 +- 4 files changed, 69 insertions(+), 41 deletions(-) diff --git a/BetterFriendship/BetterFriendship/BubbleDrawer.cs b/BetterFriendship/BetterFriendship/BubbleDrawer.cs index 326d088..488d514 100644 --- a/BetterFriendship/BetterFriendship/BubbleDrawer.cs +++ b/BetterFriendship/BetterFriendship/BubbleDrawer.cs @@ -99,41 +99,35 @@ public void DrawBubble(SpriteBatch spriteBatch, Character character, List<(Objec { DrawThoughtBubble(spriteBatch, xPosition, yPosition + hoverVal); - try - { - var objectSourceRect = Game1.getSourceRectForStandardTileSheet(Game1.objectSpriteSheet, + var objectSourceRect = Game1.getSourceRectForStandardTileSheet(Game1.objectSpriteSheet, bestItems[selectedItem].item.ParentSheetIndex, 16, 16); - spriteBatch.Draw(Game1.objectSpriteSheet, Game1.GlobalToLocal(Game1.viewport, new Vector2( - xPosition + BubbleOffset.X + 8, - yPosition - BubbleOffset.Y + hoverVal + 8)), - objectSourceRect, - Color.White * 0.75f, 0.0f, Vector2.Zero, 4f, SpriteEffects.None, - 1); + spriteBatch.Draw(Game1.objectSpriteSheet, Game1.GlobalToLocal(Game1.viewport, new Vector2( + xPosition + BubbleOffset.X + 8, + yPosition - BubbleOffset.Y + hoverVal + 8)), + objectSourceRect, + Color.White * 0.75f, 0.0f, Vector2.Zero, 4f, SpriteEffects.None, + 1); - var smileySourceRect = GetSmileySourceRect(bestItems[selectedItem].taste); + var smileySourceRect = GetSmileySourceRect(bestItems[selectedItem].taste); - spriteBatch.Draw(_emojiTexture2D, Game1.GlobalToLocal(Game1.viewport, new Vector2( - xPosition + BubbleOffset.X + 50, - yPosition - BubbleOffset.Y + hoverVal + 60)), - smileySourceRect, - Color.White * 0.75f, 0.0f, Vector2.Zero, 3f, SpriteEffects.None, - 2); + spriteBatch.Draw(_emojiTexture2D, Game1.GlobalToLocal(Game1.viewport, new Vector2( + xPosition + BubbleOffset.X + 50, + yPosition - BubbleOffset.Y + hoverVal + 60)), + smileySourceRect, + Color.White * 0.75f, 0.0f, Vector2.Zero, 3f, SpriteEffects.None, + 2); - if (bestItems[selectedItem].item.Quality is 0) return; + if (bestItems[selectedItem].item.Quality is 0) return; - var qualitySourceRect = GetQualitySourceRect(bestItems[selectedItem].item.Quality); + var qualitySourceRect = GetQualitySourceRect(bestItems[selectedItem].item.Quality); - spriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, new Vector2( - xPosition + BubbleOffset.X + 3, - yPosition - BubbleOffset.Y + hoverVal + 61)), - qualitySourceRect, - Color.White * 0.75f, 0.0f, Vector2.Zero, 3f, SpriteEffects.None, - 2); - } - catch (Exception) - { - } + spriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, new Vector2( + xPosition + BubbleOffset.X + 3, + yPosition - BubbleOffset.Y + hoverVal + 61)), + qualitySourceRect, + Color.White * 0.75f, 0.0f, Vector2.Zero, 3f, SpriteEffects.None, + 2); break; } diff --git a/BetterFriendship/BetterFriendship/GameExtensions.cs b/BetterFriendship/BetterFriendship/GameExtensions.cs index 43263e9..607b7e1 100644 --- a/BetterFriendship/BetterFriendship/GameExtensions.cs +++ b/BetterFriendship/BetterFriendship/GameExtensions.cs @@ -13,10 +13,11 @@ public static bool IsTownsfolk(this NPC npc) && npc is not Horse && npc is not Junimo && npc is not JunimoHarvester - && npc is not TrashBear; + && npc is not TrashBear + && npc.Name != "Henchman"; } - public static List<(Object, int)> GetTopGiftSuggestions(this NPC npc, ModConfig config) + public static List<(Object, int)> GetGiftSuggestions(this NPC npc, ModConfig config) { return Game1.player.Items.Where(x => x is Object) diff --git a/BetterFriendship/BetterFriendship/ModEntry.cs b/BetterFriendship/BetterFriendship/ModEntry.cs index cb8352b..5c700c5 100644 --- a/BetterFriendship/BetterFriendship/ModEntry.cs +++ b/BetterFriendship/BetterFriendship/ModEntry.cs @@ -8,6 +8,7 @@ using Object = StardewValley.Object; using System.Runtime.Caching; using System.ComponentModel; +using Microsoft.Xna.Framework; namespace BetterFriendship { @@ -87,28 +88,29 @@ npc is Child || if ((!Config.DisplayTalkPrompts && !npc.ShouldOverrideForSpouse(Config)) || friendship.TalkedToToday || npc.IsOutOfDialog()) continue; - BubbleDrawer.DrawBubble(Game1.spriteBatch, npc, null, false, true); + DrawBubbleSafely(npc, null, false, true); + continue; } List<(Object, int)> bestItems; - if (_cache.Contains(npc.Name)) + if (_cache.Contains(GetCacheKey(npc))) { - bestItems = _cache.Get(npc.Name) as List<(Object, int)>; + bestItems = _cache.Get(GetCacheKey(npc)) as List<(Object, int)>; } else { - bestItems = npc.GetTopGiftSuggestions(Config); - _cache.Add(new CacheItem(npc.Name, bestItems), + bestItems = GetGiftSuggestionsSafely(npc); + _cache.Add(new CacheItem(GetCacheKey(npc), bestItems), new CacheItemPolicy() { AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(5) }); } - BubbleDrawer.DrawBubble(Game1.spriteBatch, npc, bestItems, - true, - (Config.DisplayTalkPrompts || npc.ShouldOverrideForSpouse(Config)) && !friendship.TalkedToToday && - !npc.IsOutOfDialog() - ); + var displayTalk = (Config.DisplayTalkPrompts || npc.ShouldOverrideForSpouse(Config)) && + !friendship.TalkedToToday && + !npc.IsOutOfDialog(); + + DrawBubbleSafely(npc, bestItems, true, displayTalk); } } @@ -121,6 +123,37 @@ private static bool FriendshipCanDecay(NPC npc, Friendship friendship) return (!isPreBouquet && friendship.Points < 2500) || (isPreBouquet && friendship.Points < 2000); } + private static string GetCacheKey(Character character) => $"{Game1.player.Name}:{character.Name}"; + + private List<(Object, int)> GetGiftSuggestionsSafely(NPC npc) + { + try + { + return npc.GetGiftSuggestions(Config); + } + catch (NullReferenceException ex) + { + Monitor.VerboseLog( + $"Error with GetTopGiftSuggestion for {npc.Name}. Exception: {ex.Message}"); + return new List<(Object, int)>(); + } + } + + private void DrawBubbleSafely(Character character, List<(Object, int)> bestItems, bool displayGift, bool displayTalk) + { + try + { + BubbleDrawer.DrawBubble(Game1.spriteBatch, character, bestItems, + displayGift, + displayTalk + ); + } + catch (Exception ex) + { + Monitor.VerboseLog( + $"Error with DrawBubble for {character.Name} | bestItems: {bestItems} | displayGift: {displayGift} | displayTalk: {displayTalk}. Exception: {ex.Message}"); + } + } private void OnConfigChanged(object sender, PropertyChangedEventArgs e) { diff --git a/BetterFriendship/BetterFriendship/manifest.json b/BetterFriendship/BetterFriendship/manifest.json index 9d6fe6b..f5c5916 100644 --- a/BetterFriendship/BetterFriendship/manifest.json +++ b/BetterFriendship/BetterFriendship/manifest.json @@ -1,7 +1,7 @@ { "Name": "Better Friendship", "Author": "Urbanyeti", - "Version": "1.0.5", + "Version": "1.0.6", "Description": "Adds thought bubbles over villagers to indicate their favorite gifts from your inventory and when they'd like to talk.", "UniqueID": "BetterFriendship", "EntryDll": "BetterFriendship.dll",