1. Welcome to the official Starbound Mod repository, Guest! Not sure how to install your mods? Check out the installation guide or check out the modding help thread for more guides.
    Outdated Mods have been moved to their own category! If you update your mod please let a moderator know so we can move it back to the active section.
    Dismiss Notice

Interaction Helper 1.0.3

Displays a popup over NPCs and animals that still need their daily interaction.

  1. Hammurabi
    This mod was made using Stardew Valley v1.11 and SMAPI v1.8; it may work with older or newer versions, but has not been tested.

    Inspired by Better Ranching, Loved Labels, and sheer frustration at chicken ranching. :)

    Quite simply, this mod displays an icon over any person, farm animal, or pet under any of the following circumstances:

    NPCs:
    * You have not yet talked to them today (Dialog icon)
    * It is their birthday and you have not yet given them a gift today (Cake icon)
    * It is nearly the end of the week and you have not given them their weekly gifts (Gift icon)

    Children:
    * You have not yet talked to / played with them today, and they are at least two weeks old (Dialog icon)

    Farm animals:
    * You have not gotten the milk that the animal has ready (Bucket icon)
    * You have not gotten the wool that the animal has ready (Shears icon)
    * You have not yet pet them today (Empty heart icon)

    Pets:
    * You have not yet pet them today (Empty heart icon)


    Additionally, the mod will check if you are also using Better Ranching. If so, then the bucket and shears icons will not be displayed for compatibility.

    Code:
    using System;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.Graphics;
    using StardewModdingAPI;
    using StardewModdingAPI.Events;
    using StardewValley;
    using StardewValley.Characters;
    
    namespace InteractionHelper {
       public class InteractionHelper : Mod
      {
         private Texture2D symbols = null;
         private Config config;
         private IModHelper modHelper;
         private int tickType = 1;
         private bool betterRanchingDetected;
    
         private const int heart = 0;
         private const int talk = 1;
         private const int birthday = 2;
         private const int gift = 3;
         private const int milkPail = 4;
         private const int shears = 5;
    
         private const int spriteSize = 32;
    
         public override void Entry(IModHelper helper) {
           modHelper = helper;
           TimeEvents.DayOfMonthChanged += AfterLoad;
           GameEvents.HalfSecondTick += ToggleDisplayType;
           GraphicsEvents.OnPreRenderHudEvent += DisplayIcons;
    
           config = helper.ReadConfig<Config>();
         }
    
         public void AfterLoad(object sender, EventArgs e) {
           try {
             symbols = new ContentManager(Game1.content.ServiceProvider, modHelper.DirectoryPath + "\\").Load<Texture2D>("Symbols");
           }
           catch (Exception ex) {
             Monitor.Log($"Failed to load symbol texture: {ex.Message}", LogLevel.Error);
           }
    
           IModRegistry modRegistry = (IModRegistry) typeof(Program).GetField("ModRegistry", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.FlattenHierarchy).GetValue(null);
           if (modRegistry.IsLoaded("BetterRanching")) {
             betterRanchingDetected = true;
             Monitor.Log("Better Ranching detected. Farm animal displays will be partially suppressed for compatibility.", LogLevel.Info);
           }
    
           TimeEvents.DayOfMonthChanged -= AfterLoad;
         }
    
         public void ToggleDisplayType(object sender, EventArgs e) {
           tickType = (tickType + 1) % 2;
         }
    
         public void DisplayIcons(object sender, EventArgs e) {
           if (symbols != null) {
             foreach (Character c in Game1.currentLocation.characters) {
               ProcessCharacter(c);
             }
    
             if (Game1.currentLocation is Farm) {
               foreach (FarmAnimal f in ((Farm) Game1.currentLocation).animals.Values) {
                 ProcessFarmAnimal(f);
               }
             }
             else if (Game1.currentLocation is AnimalHouse) {
               foreach (FarmAnimal f in ((AnimalHouse) Game1.currentLocation).animals.Values) {
                 ProcessFarmAnimal(f);
               }
             }
           }
         }
    
         public void ProcessCharacter(Character c) {
           if (c is Horse) { return; }
           if (c is Junimo) { return; }
           if (c is StardewValley.Monsters.Monster) { return; }
           if ("Gunther".Equals(c.name)) { return; }
           if ("Marlon".Equals(c.name)) { return; }
           if ("Dwarf".Equals(c.name) && !config.showDwarf) { return; }
           if ("Krobus".Equals(c.name) && !config.showKrobus) { return; }
    
           if (c is Pet) { ProcessPet((Pet) c); }
           else if (c is NPC && Game1.NPCGiftTastes.ContainsKey(c.name)) { ProcessNPC((NPC) c); }
           else if (c is Child) { ProcessChild((Child) c); }
         }
    
         public void ProcessFarmAnimal(FarmAnimal farmAnimal) {
           if (!betterRanchingDetected || farmAnimal.currentProduce == -1 || farmAnimal.harvestType == 0 || string.IsNullOrWhiteSpace(farmAnimal.toolUsedForHarvest)) {
             bool wideSprite = !farmAnimal.isCoopDweller();
             float verticalOffset = farmAnimal.isCoopDweller() ? -(Game1.tileSize * (4f / 3f)) : -(Game1.tileSize * (2f / 3f));
    
             if (config.showFarmAnimalProduceIndicator && farmAnimal.currentProduce >= 0 && farmAnimal.harvestType == 1 && "Shears".Equals(farmAnimal.toolUsedForHarvest)) { ShowDisplay(farmAnimal, shears, wideSprite, verticalOffset); }
             else if (config.showFarmAnimalProduceIndicator && farmAnimal.currentProduce >= 0 && farmAnimal.harvestType == 1 && "Milk Pail".Equals(farmAnimal.toolUsedForHarvest)) { ShowDisplay(farmAnimal, milkPail, wideSprite, verticalOffset); }
             else if (config.showFarmAnimalHeartIndicator && !farmAnimal.wasPet) { ShowDisplay(farmAnimal, heart, wideSprite, verticalOffset); }
           }
         }
    
         public void ProcessPet(Pet pet) {
           if (config.showCatOrDogHeartIndicator && !modHelper.Reflection.GetPrivateField<bool>(pet, "wasPetToday", true).GetValue()) {
             ShowDisplay(pet, heart, true, -(Game1.tileSize * (2f/3f)));
           }
         }
    
         public void ProcessNPC(NPC npc) {
           if (Game1.player.friendships.ContainsKey(npc.name)) {
             bool needsBirthdayGift = config.showBirthdayIndicator && npc.isBirthday(Game1.currentSeason, Game1.dayOfMonth) && Game1.player.friendships[npc.name][3] != 1;
             bool needsRegularGift = config.showGiftIndicator && ((Game1.dayOfMonth % 7) - 4) > Game1.player.friendships[npc.name][1];
             bool needsDailyTalk = config.showTalkIndicator && !Game1.player.hasPlayerTalkedToNPC(npc.name);
    
             if ((needsBirthdayGift || needsRegularGift) && needsDailyTalk) {
               if (tickType == 0) { ShowDisplay(npc, needsBirthdayGift ? birthday : gift, false, -(Game1.tileSize * 1.5f)); }
               else { ShowDisplay(npc, talk, false, -(Game1.tileSize * 1.5f)); }
             }
             else if (needsBirthdayGift) { ShowDisplay(npc, birthday, false, -(Game1.tileSize * 1.5f)); }
             else if (needsRegularGift) { ShowDisplay(npc, gift, false, -(Game1.tileSize * 1.5f)); }
             else if (needsDailyTalk) { ShowDisplay(npc, talk, false, -(Game1.tileSize * 1.5f)); }
           }
           else {
             ShowDisplay(npc, talk, false, -(Game1.tileSize * 1.5f));
           }
         }
    
         public void ProcessChild(Child child) {
           if (config.showTalkIndicator && child.age >= 1 && (!Game1.player.friendships.ContainsKey(child.name) || !Game1.player.hasPlayerTalkedToNPC(child.name))) {
             ShowDisplay(child, talk, false, -(Game1.tileSize * 1.5f));
           }
         }
    
         private void ShowDisplay(Character c, int symbolID, bool wideSprite, float verticalOffset) {
           float horizontalOffset = (wideSprite && (c.facingDirection == 0 || c.facingDirection == 2)) ? c.Sprite.getWidth() : c.Sprite.getWidth() / 2f;
    
           float bobOffset = (float) (4.0 * Math.Round(Math.Sin(DateTime.Now.TimeOfDay.TotalMilliseconds / 250.0), 2));
           Game1.spriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, new Vector2(c.Position.X + horizontalOffset, c.Position.Y - c.Sprite.getHeight() + verticalOffset + bobOffset)), new Rectangle?(new Rectangle(141, 465, 20, 24)), Color.White * 0.75f, 0.0f, Vector2.Zero, 4f, SpriteEffects.None, 0.0f);
           Game1.spriteBatch.Draw(symbols, Game1.GlobalToLocal(Game1.viewport, new Vector2(c.Position.X + horizontalOffset + (Game1.tileSize * 9 / 20), c.Position.Y - c.Sprite.getHeight() + verticalOffset + (Game1.tileSize * 0.5f) + bobOffset)), new Rectangle?(GetSpriteRectangle(symbolID)), Color.White * 0.75f, 0.0f, new Vector2(8f, 8f), Game1.pixelZoom * 0.35f, SpriteEffects.None, 1f);
         }
    
         private Rectangle GetSpriteRectangle(int symbolID) {
           int x = symbolID % 2;
           int y = (symbolID - x) / 2;
           return new Rectangle(x * spriteSize, y * spriteSize, spriteSize, spriteSize);
         }
       }
    
       public class Config {
         public bool showDwarf { get; set; } = true;
         public bool showKrobus { get; set; } = true;
    
         public bool showBirthdayIndicator { get; set; } = true;
         public bool showGiftIndicator { get; set; } = true;
         public bool showTalkIndicator { get; set; } = true;
         public bool showCatOrDogHeartIndicator { get; set; } = true;
         public bool showFarmAnimalHeartIndicator { get; set; } = true;
         public bool showFarmAnimalProduceIndicator { get; set; } = true;
       }
    }
    

    Code:
    using System;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.Graphics;
    using StardewModdingAPI;
    using StardewModdingAPI.Events;
    using StardewValley;
    using StardewValley.Characters;
    
    namespace InteractionHelper {
       public class InteractionHelper : Mod
      {
         private Texture2D symbols = null;
         private Config config;
         private IModHelper modHelper;
         private int tickType = 1;
         private bool betterRanchingDetected;
    
         private const int heart = 0;
         private const int talk = 1;
         private const int birthday = 2;
         private const int gift = 3;
         private const int milkPail = 4;
         private const int shears = 5;
    
         private const int spriteSize = 32;
    
         public override void Entry(IModHelper helper) {
           modHelper = helper;
           TimeEvents.DayOfMonthChanged += AfterLoad;
           GameEvents.HalfSecondTick += ToggleDisplayType;
           GraphicsEvents.OnPreRenderHudEvent += DisplayIcons;
    
           config = helper.ReadConfig<Config>();
         }
    
         public void AfterLoad(object sender, EventArgs e) {
           try {
             symbols = new ContentManager(Game1.content.ServiceProvider, modHelper.DirectoryPath + "\\").Load<Texture2D>("Symbols");
           }
           catch (Exception ex) {
             Monitor.Log($"Failed to load symbol texture: {ex.Message}", LogLevel.Error);
           }
    
           IModRegistry modRegistry = (IModRegistry) typeof(Program).GetField("ModRegistry", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.FlattenHierarchy).GetValue(null);
           if (modRegistry.IsLoaded("BetterRanching")) {
             betterRanchingDetected = true;
             Monitor.Log("Better Ranching detected. Farm animal displays will be partially suppressed for compatibility.", LogLevel.Info);
           }
    
           TimeEvents.DayOfMonthChanged -= AfterLoad;
         }
    
         public void ToggleDisplayType(object sender, EventArgs e) {
           tickType = (tickType + 1) % 2;
         }
    
         public void DisplayIcons(object sender, EventArgs e) {
           if (symbols != null) {
             foreach (Character c in Game1.currentLocation.characters) {
               if (!(c is Horse) && !"Gunther".Equals(c.name) && (config.showDwarf || !"Dwarf".Equals(c.name)) && (config.showKrobus || !"Krobus".Equals(c.name))) {
                 if (c is Pet) { ProcessPet((Pet) c); }
                 else if (c is NPC) { ProcessNPC((NPC) c); }
               }
             }
    
             if (Game1.currentLocation is Farm) {
               foreach (FarmAnimal f in ((Farm) Game1.currentLocation).animals.Values) {
                 ProcessFarmAnimal(f);
               }
             }
             else if (Game1.currentLocation is AnimalHouse) {
               foreach (FarmAnimal f in ((AnimalHouse) Game1.currentLocation).animals.Values) {
                 ProcessFarmAnimal(f);
               }
             }
           }
         }
    
         public void ProcessFarmAnimal(FarmAnimal farmAnimal) {
           if (!betterRanchingDetected || farmAnimal.currentProduce == -1 || farmAnimal.harvestType == 0 || string.IsNullOrWhiteSpace(farmAnimal.toolUsedForHarvest)) {
             bool wideSprite = !farmAnimal.isCoopDweller();
             float verticalOffset = farmAnimal.isCoopDweller() ? -(Game1.tileSize * (4f / 3f)) : -(Game1.tileSize * (2f / 3f));
    
             if (config.showFarmAnimalProduceIndicator && farmAnimal.currentProduce >= 0 && farmAnimal.harvestType == 1 && "Shears".Equals(farmAnimal.toolUsedForHarvest)) { ShowDisplay(farmAnimal, shears, wideSprite, verticalOffset); }
             else if (config.showFarmAnimalProduceIndicator && farmAnimal.currentProduce >= 0 && farmAnimal.harvestType == 1 && "Milk Pail".Equals(farmAnimal.toolUsedForHarvest)) { ShowDisplay(farmAnimal, milkPail, wideSprite, verticalOffset); }
             else if (config.showFarmAnimalHeartIndicator && !farmAnimal.wasPet) { ShowDisplay(farmAnimal, heart, wideSprite, verticalOffset); }
           }
         }
    
         public void ProcessPet(Pet pet) {
           if (config.showCatOrDogHeartIndicator && !modHelper.Reflection.GetPrivateField<bool>(pet, "wasPetToday", true).GetValue()) {
             ShowDisplay(pet, heart, true, -(Game1.tileSize * (2f/3f)));
           }
         }
    
         public void ProcessNPC(NPC npc) {
           if (Game1.player.friendships.ContainsKey(npc.name)) {
             bool needsBirthdayGift = config.showBirthdayIndicator && npc.isBirthday(Game1.currentSeason, Game1.dayOfMonth) && Game1.player.friendships[npc.name][3] != 1;
             bool needsRegularGift = config.showGiftIndicator && ((Game1.dayOfMonth % 7) - 4) > Game1.player.friendships[npc.name][1];
             bool needsDailyTalk = config.showTalkIndicator && !Game1.player.hasPlayerTalkedToNPC(npc.name);
    
             if ((needsBirthdayGift || needsRegularGift) && needsDailyTalk) {
               if (tickType == 0) { ShowDisplay(npc, needsBirthdayGift ? birthday : gift, false, -(Game1.tileSize * 1.5f)); }
               else { ShowDisplay(npc, talk, false, -(Game1.tileSize * 1.5f)); }
             }
             else if (needsBirthdayGift) { ShowDisplay(npc, birthday, false, -(Game1.tileSize * 1.5f)); }
             else if (needsRegularGift) { ShowDisplay(npc, gift, false, -(Game1.tileSize * 1.5f)); }
             else if (needsDailyTalk) { ShowDisplay(npc, talk, false, -(Game1.tileSize * 1.5f)); }
           }
           else {
             ShowDisplay(npc, talk, false, -(Game1.tileSize * 1.5f));
           }
         }
    
         private void ShowDisplay(Character c, int symbolID, bool wideSprite, float verticalOffset) {
           float horizontalOffset = (wideSprite && (c.facingDirection == 0 || c.facingDirection == 2)) ? c.Sprite.getWidth() : c.Sprite.getWidth() / 2f;
    
           float bobOffset = (float) (4.0 * Math.Round(Math.Sin(DateTime.Now.TimeOfDay.TotalMilliseconds / 250.0), 2));
           Game1.spriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, new Vector2(c.Position.X + horizontalOffset, c.Position.Y - c.Sprite.getHeight() + verticalOffset + bobOffset)), new Rectangle?(new Rectangle(141, 465, 20, 24)), Color.White * 0.75f, 0.0f, Vector2.Zero, 4f, SpriteEffects.None, 0.0f);
           Game1.spriteBatch.Draw(symbols, Game1.GlobalToLocal(Game1.viewport, new Vector2(c.Position.X + horizontalOffset + (Game1.tileSize * 9 / 20), c.Position.Y - c.Sprite.getHeight() + verticalOffset + (Game1.tileSize * 0.5f) + bobOffset)), new Rectangle?(GetSpriteRectangle(symbolID)), Color.White * 0.75f, 0.0f, new Vector2(8f, 8f), Game1.pixelZoom * 0.35f, SpriteEffects.None, 1f);
         }
    
         private Rectangle GetSpriteRectangle(int symbolID) {
           int x = symbolID % 2;
           int y = (symbolID - x) / 2;
           return new Rectangle(x * spriteSize, y * spriteSize, spriteSize, spriteSize);
         }
       }
    
       public class Config {
         public bool showDwarf { get; set; } = true;
         public bool showKrobus { get; set; } = true;
    
         public bool showBirthdayIndicator { get; set; } = true;
         public bool showGiftIndicator { get; set; } = true;
         public bool showTalkIndicator { get; set; } = true;
         public bool showCatOrDogHeartIndicator { get; set; } = true;
         public bool showFarmAnimalHeartIndicator { get; set; } = true;
         public bool showFarmAnimalProduceIndicator { get; set; } = true;
       }
    }
    

    Code:
    using System;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.Graphics;
    using StardewModdingAPI;
    using StardewModdingAPI.Events;
    using StardewValley;
    using StardewValley.Characters;
    
    namespace InteractionHelper {
       public class InteractionHelper : Mod
      {
         private Texture2D symbols = null;
         private IModHelper modHelper;
         private int tickType = 1;
         private bool betterRanchingDetected;
    
         private const int heart = 0;
         private const int talk = 1;
         private const int birthday = 2;
         private const int gift = 3;
         private const int milkPail = 4;
         private const int shears = 5;
    
         private const int spriteSize = 32;
    
         public override void Entry(IModHelper helper) {
           modHelper = helper;
           TimeEvents.DayOfMonthChanged += AfterLoad;
           GameEvents.HalfSecondTick += ToggleDisplayType;
           GraphicsEvents.OnPreRenderHudEvent += DisplayIcons;
    
           Monitor.Log($"Talk ({talk}) = {GetSpriteRectangle(talk).X},{GetSpriteRectangle(talk).Y}", LogLevel.Info);
           Monitor.Log($"BDay ({birthday}) = {GetSpriteRectangle(birthday).X},{GetSpriteRectangle(birthday).Y}", LogLevel.Info);
           Monitor.Log($"Gift ({gift}) = {GetSpriteRectangle(gift).X},{GetSpriteRectangle(gift).Y}", LogLevel.Info);
           Monitor.Log($"Pail ({milkPail}) = {GetSpriteRectangle(milkPail).X},{GetSpriteRectangle(milkPail).Y}", LogLevel.Info);
           Monitor.Log($"Shrs ({shears}) = {GetSpriteRectangle(shears).X},{GetSpriteRectangle(shears).Y}", LogLevel.Info);
         }
    
         public void AfterLoad(object sender, EventArgs e) {
           try {
             symbols = new ContentManager(Game1.content.ServiceProvider, modHelper.DirectoryPath + "\\").Load<Texture2D>("Symbols");
           }
           catch (Exception ex) {
             Monitor.Log($"Failed to load symbol texture: {ex.Message}", LogLevel.Error);
           }
    
           IModRegistry modRegistry = (IModRegistry) typeof(Program).GetField("ModRegistry", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.FlattenHierarchy).GetValue(null);
           if (modRegistry.IsLoaded("BetterRanching")) {
             betterRanchingDetected = true;
             Monitor.Log("Better Ranching detected. Farm animal displays will be partially suppressed for compatibility.", LogLevel.Info);
           }
    
           TimeEvents.DayOfMonthChanged -= AfterLoad;
         }
    
         public void ToggleDisplayType(object sender, EventArgs e) {
           tickType = (tickType + 1) % 2;
         }
    
         public void DisplayIcons(object sender, EventArgs e) {
           if (symbols != null) {
             foreach (Character c in Game1.currentLocation.characters) {
               if (c is Pet) { ProcessPet((Pet) c); }
               else if (c is NPC) { ProcessNPC((NPC) c); }
             }
    
             if (Game1.currentLocation is Farm) {
               foreach (FarmAnimal f in ((Farm) Game1.currentLocation).animals.Values) {
                 ProcessFarmAnimal(f);
               }
             }
             else if (Game1.currentLocation is AnimalHouse) {
               foreach (FarmAnimal f in ((AnimalHouse) Game1.currentLocation).animals.Values) {
                 ProcessFarmAnimal(f);
               }
             }
           }
         }
    
         public void ProcessFarmAnimal(FarmAnimal farmAnimal) {
           if (!betterRanchingDetected || farmAnimal.currentProduce == -1) {
             if (farmAnimal.currentProduce >= 0 && farmAnimal.harvestType == 1 && "Shears".Equals(farmAnimal.toolUsedForHarvest)) { ShowDisplay(farmAnimal, shears); }
             else if (farmAnimal.currentProduce >= 0 && farmAnimal.harvestType == 1 && "Milk Pail".Equals(farmAnimal.toolUsedForHarvest)) { ShowDisplay(farmAnimal, milkPail); }
             else if (!farmAnimal.wasPet) { ShowDisplay(farmAnimal, heart); }
           }
         }
    
         public void ProcessPet(Pet pet) {
           if (!modHelper.Reflection.GetPrivateField<bool>(pet, "wasPetToday", true).GetValue()) {
             ShowDisplay(pet, heart);
           }
         }
    
         public void ProcessNPC(NPC npc) {
           if (Game1.player.friendships.ContainsKey(npc.name)) {
             bool needsBirthdayGift = npc.isBirthday(Game1.currentSeason, Game1.dayOfMonth) && Game1.player.friendships[npc.name][3] != 1;
             bool needsRegularGift = ((Game1.dayOfMonth % 7) - 4) > Game1.player.friendships[npc.name][1];
             bool needsDailyTalk = !Game1.player.hasPlayerTalkedToNPC(npc.name);
    
             if ((needsBirthdayGift || needsRegularGift) && needsDailyTalk) {
               if (tickType == 0) { ShowDisplay(npc, needsBirthdayGift ? birthday : gift); }
               else { ShowDisplay(npc, talk); }
             }
             else if (needsBirthdayGift) { ShowDisplay(npc, birthday); }
             else if (needsRegularGift) { ShowDisplay(npc, gift); }
             else if (needsDailyTalk) { ShowDisplay(npc, talk); }
           }
           else {
             ShowDisplay(npc, talk);
           }
         }
    
         private void ShowDisplay(Character c, int symbolID) {
           float bobOffset = (float) (4.0 * Math.Round(Math.Sin(DateTime.Now.TimeOfDay.TotalMilliseconds / 250.0), 2));
           Game1.spriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, new Vector2(c.Position.X + (c.Sprite.getWidth() / 2), c.Position.Y - (Game1.tileSize * 4 / 3) + bobOffset)), new Rectangle?(new Rectangle(141, 465, 20, 24)), Color.White * 0.75f, 0.0f, Vector2.Zero, 4f, SpriteEffects.None, 0.0f);
           Game1.spriteBatch.Draw(symbols, Game1.GlobalToLocal(Game1.viewport, new Vector2(c.Position.X + (c.Sprite.getWidth() / 2) + (Game1.tileSize * 9 / 20), c.Position.Y - (Game1.tileSize * 17 / 20) + bobOffset)), new Rectangle?(GetSpriteRectangle(symbolID)), Color.White * 0.75f, 0.0f, new Vector2(8f, 8f), Game1.pixelZoom * 0.35f, SpriteEffects.None, 1f);
         }
    
         private Rectangle GetSpriteRectangle(int symbolID) {
           int x = symbolID % 2;
           int y = (symbolID - x) / 2;
           return new Rectangle(x * spriteSize, y * spriteSize, spriteSize, spriteSize);
         }
       }
    }
    
    Mod Pack Permissions:
    Anyone can use this mod in their mod compilation without the author's consent.
    Mod Assets Permissions:
    Anyone can alter/redistribute the mod's assets without the author's consent.

    Images

    1. Example1.png
    2. Example2.png
    3. Symbols.png
    imoumou likes this.

Recent Updates

  1. v1.0.3
  2. v1.0.2
  3. v1.0.1

Recent Reviews

  1. Voortex
    Voortex
    4/5,
    Version: 1.0.3
    Unfortunately this mod is not compatible with the newest SMAPI, pls update
  2. roo15369
    roo15369
    5/5,
    Version: 1.0.3
    good!!
  3. Sherlock.
    Sherlock.
    5/5,
    Version: 1.0.2
    十分优秀的MOD