From 9b72c0e10e23b3c150d9c82854c7111c9090589f Mon Sep 17 00:00:00 2001 From: mushymato Date: Wed, 20 Nov 2024 22:31:14 -0500 Subject: [PATCH 1/8] Add content patcher apis, setup content pack --- Ornithologists Guild.sln | 12 +-- .../OrnithologistsGuild.CP.csproj | 24 ------ OrnithologistsGuild.CP/manifest.json | 2 +- .../OrnithologistsGuild.csproj | 75 ++++--------------- .../Utilities/IContentPatcherApi.cs | 41 ++++++++++ .../Utilities/IManagedConditions.cs | 37 +++++++++ 6 files changed, 96 insertions(+), 95 deletions(-) delete mode 100644 OrnithologistsGuild.CP/OrnithologistsGuild.CP.csproj create mode 100644 OrnithologistsGuild/Utilities/IContentPatcherApi.cs create mode 100644 OrnithologistsGuild/Utilities/IManagedConditions.cs diff --git a/Ornithologists Guild.sln b/Ornithologists Guild.sln index 70bef60..73fcc27 100644 --- a/Ornithologists Guild.sln +++ b/Ornithologists Guild.sln @@ -1,30 +1,20 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 25.0.1703.8 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OrnithologistsGuild", "OrnithologistsGuild\OrnithologistsGuild.csproj", "{CEF6B6C8-5644-4667-A031-196A395EEB3E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OrnithologistsGuild.CP", "OrnithologistsGuild.CP\OrnithologistsGuild.CP.csproj", "{26BFD301-759D-4C15-954B-26EA70CA7019}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {259E4387-0EC9-480C-AF1B-25568BF7477F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {259E4387-0EC9-480C-AF1B-25568BF7477F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {259E4387-0EC9-480C-AF1B-25568BF7477F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {259E4387-0EC9-480C-AF1B-25568BF7477F}.Release|Any CPU.Build.0 = Release|Any CPU {CEF6B6C8-5644-4667-A031-196A395EEB3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CEF6B6C8-5644-4667-A031-196A395EEB3E}.Debug|Any CPU.Build.0 = Debug|Any CPU {CEF6B6C8-5644-4667-A031-196A395EEB3E}.Release|Any CPU.ActiveCfg = Release|Any CPU {CEF6B6C8-5644-4667-A031-196A395EEB3E}.Release|Any CPU.Build.0 = Release|Any CPU - {26BFD301-759D-4C15-954B-26EA70CA7019}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {26BFD301-759D-4C15-954B-26EA70CA7019}.Debug|Any CPU.Build.0 = Debug|Any CPU - {26BFD301-759D-4C15-954B-26EA70CA7019}.Release|Any CPU.ActiveCfg = Release|Any CPU - {26BFD301-759D-4C15-954B-26EA70CA7019}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/OrnithologistsGuild.CP/OrnithologistsGuild.CP.csproj b/OrnithologistsGuild.CP/OrnithologistsGuild.CP.csproj deleted file mode 100644 index 6f23a51..0000000 --- a/OrnithologistsGuild.CP/OrnithologistsGuild.CP.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - net6.0 - /Users/ivy/Applications/Stardew Valley Development.app/Contents/MacOS - [CP] Ornithologists Guild - - - - - - - - - - - - - - - PreserveNewest - - - \ No newline at end of file diff --git a/OrnithologistsGuild.CP/manifest.json b/OrnithologistsGuild.CP/manifest.json index 9fd9721..ba5ddc6 100644 --- a/OrnithologistsGuild.CP/manifest.json +++ b/OrnithologistsGuild.CP/manifest.json @@ -15,7 +15,7 @@ }, { "UniqueID": "Ivy.OrnithologistsGuild", - "MinimumVersion": "1.9.2" + "MinimumVersion": "1.9.4" } ], "RequiredForEveryone": true, diff --git a/OrnithologistsGuild/OrnithologistsGuild.csproj b/OrnithologistsGuild/OrnithologistsGuild.csproj index 8feaf3d..94ec69e 100644 --- a/OrnithologistsGuild/OrnithologistsGuild.csproj +++ b/OrnithologistsGuild/OrnithologistsGuild.csproj @@ -1,75 +1,28 @@ + net6.0 - /Users/ivy/Applications/Stardew Valley.app/Contents/MacOS + OrnithologistsGuild true ThirdParty - Ornithologists Guild + Release;Debug - - - - - AfterBuild - bash ${SolutionDir}/generate_zip.sh - ${SolutionDir}/ - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - lib\ContentPatcher.dll - - - lib\MailFrameworkMod.dll - False - + + - - PreserveNewest - PreserveNewest @@ -85,8 +38,12 @@ PreserveNewest - - PreserveNewest - + + + + + False + $(GamePath)/Mods/MailFrameworkMod/MailFrameworkMod.dll + \ No newline at end of file diff --git a/OrnithologistsGuild/Utilities/IContentPatcherApi.cs b/OrnithologistsGuild/Utilities/IContentPatcherApi.cs new file mode 100644 index 0000000..a2ea252 --- /dev/null +++ b/OrnithologistsGuild/Utilities/IContentPatcherApi.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using StardewModdingAPI; +using StardewModdingAPI.Events; + +namespace ContentPatcher; + +/// The Content Patcher API which other mods can access. +public interface IContentPatcherAPI +{ + /********* + ** Accessors + *********/ + /// Whether the conditions API is initialized and ready for use. + /// Due to the Content Patcher lifecycle, the conditions API becomes available roughly two ticks after the event. + bool IsConditionsApiReady { get; } + + /********* + ** Methods + *********/ + /// Get a set of managed conditions which are matched against Content Patcher's internal context. + /// The manifest of the mod parsing the conditions (see in your entry class). + /// The conditions to parse, in the same format as When blocks in Content Patcher content packs. + /// The format version for which to parse conditions, used to ensure forward compatibility with future Content Patcher versions. See Format in the Content Patcher token documentation. + /// + /// The unique IDs of mods whose custom tokens to allow in the . You don't need to list the mod identified by , mods listed as a required dependency in the , or mods identified by a HasMod condition in the . + /// NOTE: this is meant to prevent mods from breaking if a player doesn't have a required mod installed. You shouldn't simply list all installed mods, and parsing conditions will still fail if a mod isn't installed regardless of the listed mod IDs. + /// + IManagedConditions ParseConditions( + IManifest manifest, + IDictionary rawConditions, + ISemanticVersion formatVersion, + string[] assumeModIds = null + ); + + /// Register a simple token. + /// The manifest of the mod defining the token (see in your entry class). + /// The token name. This only needs to be unique for your mod; Content Patcher will prefix it with your mod ID automatically, like YourName.ExampleMod/SomeTokenName. + /// A function which returns the current token value. If this returns a null or empty list, the token is considered unavailable in the current context and any patches or dynamic tokens using it are disabled. + void RegisterToken(IManifest mod, string name, Func> getValue); +} diff --git a/OrnithologistsGuild/Utilities/IManagedConditions.cs b/OrnithologistsGuild/Utilities/IManagedConditions.cs new file mode 100644 index 0000000..34a1df6 --- /dev/null +++ b/OrnithologistsGuild/Utilities/IManagedConditions.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace ContentPatcher; + +/// A set of parsed conditions linked to the Content Patcher context. These conditions are per-screen, so the result depends on the screen that's active when calling the members. +public interface IManagedConditions +{ + /********* + ** Accessors + *********/ + /// Whether the conditions were parsed successfully (regardless of whether they're in scope currently). + [MemberNotNullWhen(false, nameof(IManagedConditions.ValidationError))] + bool IsValid { get; } + + /// If is false, an error phrase indicating why the conditions failed to parse, formatted like this: 'seasonz' isn't a valid token name; must be one of <token list>. If the conditions are valid, this is null. + string ValidationError { get; } + + /// Whether the conditions' tokens are all valid in the current context. For example, this would be false if the conditions use Season and a save isn't loaded yet. + bool IsReady { get; } + + /// Whether is true, and the conditions all match in the current context. + bool IsMatch { get; } + + /// Whether may change depending on the context. For example, Season is mutable since it depends on the in-game season. HasMod is not mutable, since it can't change after the game is launched. + bool IsMutable { get; } + + /********* + ** Methods + *********/ + /// Update the conditions based on Content Patcher's current context for every active screen. It's safe to call this as often as you want, but it has no effect if the Content Patcher context hasn't changed since you last called it. + /// Returns the screens for which changed value. + IEnumerable UpdateContext(); + + /// If is false, analyze the conditions/context and get a human-readable reason phrase explaining why the conditions don't match the context. For example: conditions don't match: season. If the conditions do match, this returns null. + string GetReasonNotMatched(); +} From 561f64f094d0dd8010fb32abb6f7f65493785c86 Mon Sep 17 00:00:00 2001 From: mushymato Date: Thu, 21 Nov 2024 00:00:32 -0500 Subject: [PATCH 2/8] move mail to CP --- OrnithologistsGuild.CP/assets/mail.json | 76 +++++++++++++++++++ OrnithologistsGuild.CP/content.json | 5 ++ OrnithologistsGuild.CP/i18n/default.json | 14 ++++ OrnithologistsGuild/Game/GSQ.cs | 52 +++++++++++++ OrnithologistsGuild/Game/Mail.cs | 72 ------------------ OrnithologistsGuild/ModEntry.cs | 19 +++-- .../OrnithologistsGuild.csproj | 15 ---- OrnithologistsGuild/i18n/default.json | 6 -- OrnithologistsGuild/manifest.json | 3 - 9 files changed, 159 insertions(+), 103 deletions(-) create mode 100644 OrnithologistsGuild.CP/assets/mail.json create mode 100644 OrnithologistsGuild/Game/GSQ.cs delete mode 100644 OrnithologistsGuild/Game/Mail.cs diff --git a/OrnithologistsGuild.CP/assets/mail.json b/OrnithologistsGuild.CP/assets/mail.json new file mode 100644 index 0000000..c040083 --- /dev/null +++ b/OrnithologistsGuild.CP/assets/mail.json @@ -0,0 +1,76 @@ +{ + "$schema": "https://smapi.io/schemas/content-patcher.json", + "Changes": [ + // mail data + { + "Action": "EditData", + "Target": "Data/Mail", + "Entries": { + // give lifelist + "Mods_Ivy_OrnithologistsGuild_Introduction": "{{i18n: mail.Introduction}}%item id (T)Ivy_OrnithologistsGuild_LifeList %% %item conversationTopic (T)Ivy_OrnithologistsGuild_LifeList 14 %% [#]{{i18n: mail.Introduction.title}}", + // 1 bird identified, mixed seeds + "Mods_Ivy_OrnithologistsGuild_LifeList1": "{{i18n: mail.LifeList1}}%item id (O)770 5 %% [#]{{i18n: mail.LifeList1.title}}", + // 3 birds identified, corn + "Mods_Ivy_OrnithologistsGuild_LifeList3": "{{i18n: mail.LifeList3}}%item id (O)270 5 %% [#]{{i18n: mail.LifeList3.title}}", + // 5 birds identified, sunflower seeds + "Mods_Ivy_OrnithologistsGuild_LifeList5": "{{i18n: mail.LifeList5}}%item id (O)431 5 %% [#]{{i18n: mail.LifeList5.title}}", + // 7 birds identified, salmonberries + "Mods_Ivy_OrnithologistsGuild_LifeList7": "{{i18n: mail.LifeList5}}%item id (O)296 5 %% [#]{{i18n: mail.LifeList7.title}}", + // all birds identified, convo topic + "Mods_Ivy_OrnithologistsGuild_LifeListAll": "{{i18n: mail.LifeList5}}%item conversationTopic Ivy_OrnithologistGuild_LifeListAll 14 %% [#]{{i18n: mail.LifeListAll.title}}", + }, + }, + // mail sending triggers + { + "Action": "EditData", + "Target": "Data/TriggerActions", + "Entries": { + //send intro mail after spring 5 y1 + "{{ModId}}_Mail_Introduction": { + "Id": "{{ModId}}_Mail_Introduction", + "Trigger": "DayStarted", + "Condition": "DATE_RANGE spring 5 1", + // send this mail immediately on mod install (if after spring 5 y1) + "Action": "AddMail Current Mods_Ivy_OrnithologistsGuild_Introduction Now", + // TriggerAction will only send mail once when MarkActionApplied=True, this is the default behavior + // "MarkActionApplied": true + }, + // 1 bird + "{{ModId}}_Mail_LifeList1": { + "Id": "{{ModId}}_Mail_LifeList1", + "Trigger": "DayEnding", + "Condition": "Ivy.OrnithologistsGuild_IDENTIFIED_AT_LEAST 1", + "Action": "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeList1" + }, + // 3 birds + "{{ModId}}_Mail_LifeList3": { + "Id": "{{ModId}}_Mail_LifeList3", + "Trigger": "DayEnding", + "Condition": "Ivy.OrnithologistsGuild_IDENTIFIED_AT_LEAST 3", + "Action": "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeList3" + }, + // 5 birds + "{{ModId}}_Mail_LifeList5": { + "Id": "{{ModId}}_Mail_LifeList5", + "Trigger": "DayEnding", + "Condition": "Ivy.OrnithologistsGuild_IDENTIFIED_AT_LEAST 5", + "Action": "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeList5" + }, + // 7 birds + "{{ModId}}_Mail_LifeList7": { + "Id": "{{ModId}}_Mail_LifeList7", + "Trigger": "DayEnding", + "Condition": "Ivy.OrnithologistsGuild_IDENTIFIED_AT_LEAST 7", + "Action": "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeList7" + }, + // 7 birds + "{{ModId}}_Mail_LifeListAll": { + "Id": "{{ModId}}_Mail_LifeListAll", + "Trigger": "DayEnding", + "Condition": "Ivy.OrnithologistsGuild_IDENTIFIED_ALL", + "Action": "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeListAll" + }, + } + } + ] +} \ No newline at end of file diff --git a/OrnithologistsGuild.CP/content.json b/OrnithologistsGuild.CP/content.json index 1fdfcd2..2b4d687 100644 --- a/OrnithologistsGuild.CP/content.json +++ b/OrnithologistsGuild.CP/content.json @@ -44,6 +44,11 @@ { "Action": "Include", "FromFile": "assets/npc/Kyle.json" + }, + // Mail + { + "Action": "Include", + "FromFile": "assets/mail.json" } ] } \ No newline at end of file diff --git a/OrnithologistsGuild.CP/i18n/default.json b/OrnithologistsGuild.CP/i18n/default.json index 1d84d33..3fd2902 100644 --- a/OrnithologistsGuild.CP/i18n/default.json +++ b/OrnithologistsGuild.CP/i18n/default.json @@ -88,4 +88,18 @@ "event.OrnithologistsGuild_Kyle_SpellNSpeak.1": "~ H-E-L-L-O ~$6", "event.OrnithologistsGuild_Kyle_SpellNSpeak.2": "~ MY NAME IS K-Y-L-E ~$7", "event.OrnithologistsGuild_Kyle_SpellNSpeak.3": "*battery fizzling out*$10", + // mail data, moved from C# + "mail.Introduction": "Dear @, ^^Your grandmother, an avid birder of many years, left you this. We hope you find a way to continue her tradition this spring. ^^Good luck, and watch for bird's nests! ^The Pelican Town Ornithologist's Guild", + "mail.LifeList1": "Dear @, ^^Congrats, you've identified your first bird! We think these may be of some help. ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", + "mail.LifeList3": "Dear @, ^^Three birds identified! You're on a roll. Leave some of this delicious corn for the birds! ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", + "mail.LifeList5": "Dear @, ^^Five birds identified is quite the milestone. If only these Sunflower Seeds were hulled... ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", + "mail.LifeList7": "Dear @, ^^Seven birds identified!? You're becoming an expert! Perhaps the frugivores in your life will enjoy this. ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", + "mail.LifeListAll": "Dear @, ^^You've identified every bird Pelican Town has to offer! Your grandmother left you this as a reward for a job well done. She would be very proud of the birder you've become. < ^^Until next time, ^The Pelican Town Ornithologist's Guild", + // mail titles, appear in the mail collection screen + "mail.Introduction.title": "Ornithologist's Guild: Introduction", + "mail.LifeList1.title": "Ornithologist's Guild: First Bird", + "mail.LifeList3.title": "Ornithologist's Guild: Three Birds", + "mail.LifeList5.title": "Ornithologist's Guild: Five Birds", + "mail.LifeList7.title": "Ornithologist's Guild: Seven Birds", + "mail.LifeListAll.title": "Ornithologist's Guild: All Birds" } \ No newline at end of file diff --git a/OrnithologistsGuild/Game/GSQ.cs b/OrnithologistsGuild/Game/GSQ.cs new file mode 100644 index 0000000..fe65aae --- /dev/null +++ b/OrnithologistsGuild/Game/GSQ.cs @@ -0,0 +1,52 @@ +using OrnithologistsGuild.Content; +using StardewModdingAPI; +using StardewValley; +using StardewValley.Delegates; + +namespace OrnithologistsGuild +{ + /// + /// Add game state queries for use in conditions. + /// + public static class GSQ + { + private static IMonitor Monitor; + + public static void Initialize(string modId, IMonitor monitor) + { + Monitor = monitor; + + GameStateQuery.Register($"{modId}_IDENTIFIED_AT_LEAST", IDENTIFIED_AT_LEAST); + GameStateQuery.Register($"{modId}_IDENTIFIED_ALL", IDENTIFIED_ALL); + } + + /// + /// Check if the player has identified at least (>=) N birdies + /// Usage: Ivy.OrnithologistsGuild_IDENTIFIED_AT_LEAST \ + /// /// + /// GSQ query, expected to have 2 items + /// GSQ context, unused + /// + public static bool IDENTIFIED_AT_LEAST(string[] query, GameStateQueryContext context) + { + if (!ArgUtility.TryGetInt(query, 1, out int identify, out string error, "int identify")) + { + Monitor.Log(error, LogLevel.Error); + return false; + } + return SaveDataManager.SaveData.ForPlayer(Game1.player.UniqueMultiplayerID).LifeList.IdentifiedCount >= identify; + } + + /// + /// Check if the player has identified at least (>=) N birdies + /// Usage: Ivy.OrnithologistsGuild_IDENTIFIED_ALL + /// /// + /// GSQ query, expected to have 2 items + /// GSQ context, unused + /// + public static bool IDENTIFIED_ALL(string[] query, GameStateQueryContext context) + { + return SaveDataManager.SaveData.ForPlayer(Game1.player.UniqueMultiplayerID).LifeList.IdentifiedCount >= ContentPackManager.BirdieDefs.Count; + } + } +} \ No newline at end of file diff --git a/OrnithologistsGuild/Game/Mail.cs b/OrnithologistsGuild/Game/Mail.cs deleted file mode 100644 index e808e2f..0000000 --- a/OrnithologistsGuild/Game/Mail.cs +++ /dev/null @@ -1,72 +0,0 @@ -using StardewValley; -using MailFrameworkMod; -using System.Collections.Generic; -using StardewModdingAPI.Utilities; -using OrnithologistsGuild.Content; - -namespace OrnithologistsGuild -{ - public class Mail - { - public static void Initialize() - { - MailRepository.SaveLetter(new Letter( - "Mods_Ivy_OrnithologistsGuild_Introduction", - // Adds conversation topic "Ivy_OrnithologistGuild_Introduction" for 14 days - $"{I18n.Mail_Introduction()} %item conversationTopic Ivy_OrnithologistGuild_Introduction 14 %%", - new List { ItemRegistry.Create(Constants.LIFE_LIST_FQID, 1) }, - (l) => - !Game1.player.mailReceived.Contains(l.Id) && - (SDate.From(Game1.Date) >= new SDate(5, "spring", 1) || - SaveDataManager.SaveData.ForPlayer(Game1.player.UniqueMultiplayerID).LifeList.Count > 0), - (l) => Game1.player.mailReceived.Add(l.Id))); - - MailRepository.SaveLetter(new Letter( - "Mods_Ivy_OrnithologistsGuild_LifeList1", - I18n.Mail_LifeList1(), - new List { ItemRegistry.Create("(O)770" /* Mixed Seeds */, 5) }, - (l) => - !Game1.player.mailReceived.Contains(l.Id) && - SaveDataManager.SaveData.ForPlayer(Game1.player.UniqueMultiplayerID).LifeList.IdentifiedCount > 0, - (l) => Game1.player.mailReceived.Add(l.Id))); - - MailRepository.SaveLetter(new Letter( - "Mods_Ivy_OrnithologistsGuild_LifeList3", - I18n.Mail_LifeList3(), - new List { ItemRegistry.Create("(O)270" /* Corn */, 5) }, - (l) => - !Game1.player.mailReceived.Contains(l.Id) && - SaveDataManager.SaveData.ForPlayer(Game1.player.UniqueMultiplayerID).LifeList.IdentifiedCount >= 3, - (l) => Game1.player.mailReceived.Add(l.Id))); - - MailRepository.SaveLetter(new Letter( - "Mods_Ivy_OrnithologistsGuild_LifeList5", - I18n.Mail_LifeList5(), - new List { ItemRegistry.Create("(O)431" /* Sunflower Seeds */, 5) }, - (l) => - !Game1.player.mailReceived.Contains(l.Id) && - SaveDataManager.SaveData.ForPlayer(Game1.player.UniqueMultiplayerID).LifeList.IdentifiedCount >= 5, - (l) => Game1.player.mailReceived.Add(l.Id))); - - MailRepository.SaveLetter(new Letter( - "Mods_Ivy_OrnithologistsGuild_LifeList7", - I18n.Mail_LifeList7(), - new List { ItemRegistry.Create("(O)296" /* Salmonberries */, 5) }, - (l) => - !Game1.player.mailReceived.Contains(l.Id) && - SaveDataManager.SaveData.ForPlayer(Game1.player.UniqueMultiplayerID).LifeList.IdentifiedCount >= 7, - (l) => Game1.player.mailReceived.Add(l.Id))); - - MailRepository.SaveLetter(new Letter( - "Mods_Ivy_OrnithologistsGuild_LifeListAll", - // Adds conversation topic "Ivy_OrnithologistGuild_LifeListAll" for 14 days - $"{I18n.Mail_LifeListAll()} %item conversationTopic Ivy_OrnithologistGuild_LifeListAll 14 %%", - new List { ItemRegistry.Create("(O)928" /* Golden Egg */, 1) }, - (l) => - !Game1.player.mailReceived.Contains(l.Id) && - SaveDataManager.SaveData.ForPlayer(Game1.player.UniqueMultiplayerID).LifeList.IdentifiedCount >= ContentPackManager.BirdieDefs.Count, - (l) => Game1.player.mailReceived.Add(l.Id))); - } - } -} - diff --git a/OrnithologistsGuild/ModEntry.cs b/OrnithologistsGuild/ModEntry.cs index 3ddea5c..e166d08 100644 --- a/OrnithologistsGuild/ModEntry.cs +++ b/OrnithologistsGuild/ModEntry.cs @@ -7,8 +7,8 @@ using StardewModdingAPI; using StardewModdingAPI.Events; using StardewValley; -using StardewValley.Internal; - +using StardewValley.Internal; + namespace OrnithologistsGuild { /// The mod entry point. @@ -31,6 +31,7 @@ public override void Entry(IModHelper helper) Helper.Events.Input.ButtonPressed += Input_ButtonPressed; SaveDataManager.Initialize(); + GSQ.Initialize(ModManifest.UniqueID, Monitor); } private void Input_ButtonPressed(object sender, ButtonPressedEventArgs e) @@ -51,10 +52,11 @@ private void GameLoop_SaveLoaded(object sender, SaveLoadedEventArgs e) MigrateLegacyItems(); SaveDataManager.Load(); - Mail.Initialize(); + // Mail.Initialize(); NestManager.Initialize(); - if (ConfigManager.Config.LogMissingBiomes) { + if (ConfigManager.Config.LogMissingBiomes) + { foreach (var location in StardewValley.Game1.locations) { var biomes = location.GetBiomes(); @@ -80,7 +82,8 @@ private void MigrateLegacyItems() { "(O)Ivy_OrnithologistsGuild_ProBinoculars", Constants.BINOCULARS_PRO_FQID } }; - StardewValley.Internal.ForEachItemHelper.ForEachItemInWorld(delegate (in ForEachItemContext ctx) { + StardewValley.Internal.ForEachItemHelper.ForEachItemInWorld(delegate (in ForEachItemContext ctx) + { if (LegacyItemMigrations.TryGetValue(ctx.Item.QualifiedItemId, out var newQualifiedItemId)) { @@ -95,7 +98,8 @@ private void MigrateLegacyItems() try { ctx.RemoveItem(); - } catch (Exception ex2) + } + catch (Exception ex2) { Monitor.Log($"Removing broken {ctx.Item.QualifiedItemId} failed. Please manually remove the broken item.\n{ex2}", LogLevel.Error); } @@ -117,7 +121,8 @@ private void GameLoop_GameLaunched(object sender, GameLaunchedEventArgs e) return Game1.player.currentLocation.GetBiomes(); }); // Player name for PowerUp e.g. `Ivy` -> `I-V-Y` - CP.RegisterToken(ModManifest, "PowerUpPlayerName", () => { + CP.RegisterToken(ModManifest, "PowerUpPlayerName", () => + { string[] GetValue(string playerName) { return new[] { string.Join('-', playerName.ToUpper().ToCharArray()) }; diff --git a/OrnithologistsGuild/OrnithologistsGuild.csproj b/OrnithologistsGuild/OrnithologistsGuild.csproj index 94ec69e..f6c82a2 100644 --- a/OrnithologistsGuild/OrnithologistsGuild.csproj +++ b/OrnithologistsGuild/OrnithologistsGuild.csproj @@ -23,27 +23,12 @@ - - PreserveNewest - PreserveNewest - - PreserveNewest - - - PreserveNewest - PreserveNewest - - - False - $(GamePath)/Mods/MailFrameworkMod/MailFrameworkMod.dll - - \ No newline at end of file diff --git a/OrnithologistsGuild/i18n/default.json b/OrnithologistsGuild/i18n/default.json index ba14f03..76120cf 100644 --- a/OrnithologistsGuild/i18n/default.json +++ b/OrnithologistsGuild/i18n/default.json @@ -14,12 +14,6 @@ "config.aboutKyle.title": "About Kyle", "config.aboutKyle.content": "Kyle the raven was inspired by Kyle, a rescued raven I met at The Raptors in Duncan, BC, Canada. He loves to explore, paint, and meet new people.", "config.noBreakOrJam.title": "Do not break or jam binoculars", - "mail.Introduction": "Dear @, ^^Your grandmother, an avid birder of many years, left you this. We hope you find a way to continue her tradition this spring. ^^Good luck, and watch for bird's nests! ^The Pelican Town Ornithologist's Guild", - "mail.LifeList1": "Dear @, ^^Congrats, you've identified your first bird! We think these may be of some help. ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", - "mail.LifeList3": "Dear @, ^^Three birds identified! You're on a roll. Leave some of this delicious corn for the birds! ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", - "mail.LifeList5": "Dear @, ^^Five birds identified is quite the milestone. If only these Sunflower Seeds were hulled... ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", - "mail.LifeList7": "Dear @, ^^Seven birds identified!? You're becoming an expert! Perhaps the frugivores in your life will enjoy this. ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", - "mail.LifeListAll": "Dear @, ^^You've identified every bird Pelican Town has to offer! Your grandmother left you this as a reward for a job well done. She would be very proud of the birder you've become. < ^^Until next time, ^The Pelican Town Ornithologist's Guild", "items.LifeList.title": "{{playerName}}'s Life List", "items.LifeList.totalSighted": "{{count}} {{birds}} sighted", "items.LifeList.totalIdentified": "{{count}} {{birds}} identified", diff --git a/OrnithologistsGuild/manifest.json b/OrnithologistsGuild/manifest.json index 2d82785..6ff92d1 100644 --- a/OrnithologistsGuild/manifest.json +++ b/OrnithologistsGuild/manifest.json @@ -13,9 +13,6 @@ { "UniqueID": "Pathoschild.ContentPatcher", "MinimumVersion": "2.0.0" - }, - { - "UniqueID": "DIGUS.MailFrameworkMod" } ], "RequiredForEveryone": true From 8b559ef66789917938a3fb661cbe1ab82bf9685d Mon Sep 17 00:00:00 2001 From: mushymato Date: Thu, 21 Nov 2024 00:04:30 -0500 Subject: [PATCH 3/8] hmm i18n --- OrnithologistsGuild/OrnithologistsGuild.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/OrnithologistsGuild/OrnithologistsGuild.csproj b/OrnithologistsGuild/OrnithologistsGuild.csproj index f6c82a2..b5c221f 100644 --- a/OrnithologistsGuild/OrnithologistsGuild.csproj +++ b/OrnithologistsGuild/OrnithologistsGuild.csproj @@ -1,7 +1,4 @@ - - net6.0 From e7578746a6515cb6ff6a7ecf76b56f853466623e Mon Sep 17 00:00:00 2001 From: mushymato Date: Thu, 21 Nov 2024 17:34:03 -0500 Subject: [PATCH 4/8] move mail back to C# portion --- OrnithologistsGuild.CP/assets/mail.json | 76 ----------------- OrnithologistsGuild.CP/content.json | 5 -- OrnithologistsGuild.CP/i18n/default.json | 16 +--- OrnithologistsGuild/Content/ContentManager.cs | 85 ++++++++++++++++++- OrnithologistsGuild/i18n/default.json | 16 +++- 5 files changed, 100 insertions(+), 98 deletions(-) delete mode 100644 OrnithologistsGuild.CP/assets/mail.json diff --git a/OrnithologistsGuild.CP/assets/mail.json b/OrnithologistsGuild.CP/assets/mail.json deleted file mode 100644 index c040083..0000000 --- a/OrnithologistsGuild.CP/assets/mail.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "$schema": "https://smapi.io/schemas/content-patcher.json", - "Changes": [ - // mail data - { - "Action": "EditData", - "Target": "Data/Mail", - "Entries": { - // give lifelist - "Mods_Ivy_OrnithologistsGuild_Introduction": "{{i18n: mail.Introduction}}%item id (T)Ivy_OrnithologistsGuild_LifeList %% %item conversationTopic (T)Ivy_OrnithologistsGuild_LifeList 14 %% [#]{{i18n: mail.Introduction.title}}", - // 1 bird identified, mixed seeds - "Mods_Ivy_OrnithologistsGuild_LifeList1": "{{i18n: mail.LifeList1}}%item id (O)770 5 %% [#]{{i18n: mail.LifeList1.title}}", - // 3 birds identified, corn - "Mods_Ivy_OrnithologistsGuild_LifeList3": "{{i18n: mail.LifeList3}}%item id (O)270 5 %% [#]{{i18n: mail.LifeList3.title}}", - // 5 birds identified, sunflower seeds - "Mods_Ivy_OrnithologistsGuild_LifeList5": "{{i18n: mail.LifeList5}}%item id (O)431 5 %% [#]{{i18n: mail.LifeList5.title}}", - // 7 birds identified, salmonberries - "Mods_Ivy_OrnithologistsGuild_LifeList7": "{{i18n: mail.LifeList5}}%item id (O)296 5 %% [#]{{i18n: mail.LifeList7.title}}", - // all birds identified, convo topic - "Mods_Ivy_OrnithologistsGuild_LifeListAll": "{{i18n: mail.LifeList5}}%item conversationTopic Ivy_OrnithologistGuild_LifeListAll 14 %% [#]{{i18n: mail.LifeListAll.title}}", - }, - }, - // mail sending triggers - { - "Action": "EditData", - "Target": "Data/TriggerActions", - "Entries": { - //send intro mail after spring 5 y1 - "{{ModId}}_Mail_Introduction": { - "Id": "{{ModId}}_Mail_Introduction", - "Trigger": "DayStarted", - "Condition": "DATE_RANGE spring 5 1", - // send this mail immediately on mod install (if after spring 5 y1) - "Action": "AddMail Current Mods_Ivy_OrnithologistsGuild_Introduction Now", - // TriggerAction will only send mail once when MarkActionApplied=True, this is the default behavior - // "MarkActionApplied": true - }, - // 1 bird - "{{ModId}}_Mail_LifeList1": { - "Id": "{{ModId}}_Mail_LifeList1", - "Trigger": "DayEnding", - "Condition": "Ivy.OrnithologistsGuild_IDENTIFIED_AT_LEAST 1", - "Action": "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeList1" - }, - // 3 birds - "{{ModId}}_Mail_LifeList3": { - "Id": "{{ModId}}_Mail_LifeList3", - "Trigger": "DayEnding", - "Condition": "Ivy.OrnithologistsGuild_IDENTIFIED_AT_LEAST 3", - "Action": "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeList3" - }, - // 5 birds - "{{ModId}}_Mail_LifeList5": { - "Id": "{{ModId}}_Mail_LifeList5", - "Trigger": "DayEnding", - "Condition": "Ivy.OrnithologistsGuild_IDENTIFIED_AT_LEAST 5", - "Action": "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeList5" - }, - // 7 birds - "{{ModId}}_Mail_LifeList7": { - "Id": "{{ModId}}_Mail_LifeList7", - "Trigger": "DayEnding", - "Condition": "Ivy.OrnithologistsGuild_IDENTIFIED_AT_LEAST 7", - "Action": "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeList7" - }, - // 7 birds - "{{ModId}}_Mail_LifeListAll": { - "Id": "{{ModId}}_Mail_LifeListAll", - "Trigger": "DayEnding", - "Condition": "Ivy.OrnithologistsGuild_IDENTIFIED_ALL", - "Action": "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeListAll" - }, - } - } - ] -} \ No newline at end of file diff --git a/OrnithologistsGuild.CP/content.json b/OrnithologistsGuild.CP/content.json index 2b4d687..1fdfcd2 100644 --- a/OrnithologistsGuild.CP/content.json +++ b/OrnithologistsGuild.CP/content.json @@ -44,11 +44,6 @@ { "Action": "Include", "FromFile": "assets/npc/Kyle.json" - }, - // Mail - { - "Action": "Include", - "FromFile": "assets/mail.json" } ] } \ No newline at end of file diff --git a/OrnithologistsGuild.CP/i18n/default.json b/OrnithologistsGuild.CP/i18n/default.json index 3fd2902..9a13c35 100644 --- a/OrnithologistsGuild.CP/i18n/default.json +++ b/OrnithologistsGuild.CP/i18n/default.json @@ -87,19 +87,5 @@ "map.OrnithologistsGuild.strings.29": "\"Dirty feeders and baths make sick birds!\" the document proclaims before prescribing a rigorous cleaning regimen. \"Clean every two weeks, no less!\"", "event.OrnithologistsGuild_Kyle_SpellNSpeak.1": "~ H-E-L-L-O ~$6", "event.OrnithologistsGuild_Kyle_SpellNSpeak.2": "~ MY NAME IS K-Y-L-E ~$7", - "event.OrnithologistsGuild_Kyle_SpellNSpeak.3": "*battery fizzling out*$10", - // mail data, moved from C# - "mail.Introduction": "Dear @, ^^Your grandmother, an avid birder of many years, left you this. We hope you find a way to continue her tradition this spring. ^^Good luck, and watch for bird's nests! ^The Pelican Town Ornithologist's Guild", - "mail.LifeList1": "Dear @, ^^Congrats, you've identified your first bird! We think these may be of some help. ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", - "mail.LifeList3": "Dear @, ^^Three birds identified! You're on a roll. Leave some of this delicious corn for the birds! ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", - "mail.LifeList5": "Dear @, ^^Five birds identified is quite the milestone. If only these Sunflower Seeds were hulled... ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", - "mail.LifeList7": "Dear @, ^^Seven birds identified!? You're becoming an expert! Perhaps the frugivores in your life will enjoy this. ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", - "mail.LifeListAll": "Dear @, ^^You've identified every bird Pelican Town has to offer! Your grandmother left you this as a reward for a job well done. She would be very proud of the birder you've become. < ^^Until next time, ^The Pelican Town Ornithologist's Guild", - // mail titles, appear in the mail collection screen - "mail.Introduction.title": "Ornithologist's Guild: Introduction", - "mail.LifeList1.title": "Ornithologist's Guild: First Bird", - "mail.LifeList3.title": "Ornithologist's Guild: Three Birds", - "mail.LifeList5.title": "Ornithologist's Guild: Five Birds", - "mail.LifeList7.title": "Ornithologist's Guild: Seven Birds", - "mail.LifeListAll.title": "Ornithologist's Guild: All Birds" + "event.OrnithologistsGuild_Kyle_SpellNSpeak.3": "*battery fizzling out*$10" } \ No newline at end of file diff --git a/OrnithologistsGuild/Content/ContentManager.cs b/OrnithologistsGuild/Content/ContentManager.cs index c5d75fb..01c3370 100644 --- a/OrnithologistsGuild/Content/ContentManager.cs +++ b/OrnithologistsGuild/Content/ContentManager.cs @@ -1,6 +1,9 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Microsoft.Xna.Framework.Graphics; +using StardewModdingAPI; using StardewModdingAPI.Events; +using StardewValley.GameData; namespace OrnithologistsGuild.Content { @@ -29,7 +32,87 @@ private static void Content_AssetRequested(object sender, AssetRequestedEventArg { e.LoadFromModFile("assets/binoculars.png", AssetLoadPriority.Low); } + // mail & triggers + // this can be done in content patcher ofc, kept here for i18n key. + if (e.Name.IsEquivalentTo("Data/Mail")) + { + e.Edit(Edit_DataMail); + } + if (e.Name.IsEquivalentTo("Data/TriggerActions")) + { + e.Edit(Edit_DataTriggerActions); + } } + + private static void Edit_DataMail(IAssetData data) + { + var mail = data.AsDictionary().Data; + // give lifelist + mail["Mods_Ivy_OrnithologistsGuild_Introduction"] = $"{I18n.Mail_Introduction()}%item id (T)Ivy_OrnithologistsGuild_LifeList %% %item conversationTopic Ivy_OrnithologistGuild_Introduction 14 %% [#]{I18n.Mail_Introduction_Title()}"; + // 1 bird identified, mixed seeds + mail["Mods_Ivy_OrnithologistsGuild_LifeList1"] = $"{I18n.Mail_LifeList1()}%item id (O)770 5 %% [#]{I18n.Mail_LifeList1_Title()}"; + // 3 birds identified, corn + mail["Mods_Ivy_OrnithologistsGuild_LifeList3"] = $"{I18n.Mail_LifeList3()}%item id (O)270 5 %% [#]{I18n.Mail_LifeList3_Title()}"; + // 5 birds identified, sunflower seeds + mail["Mods_Ivy_OrnithologistsGuild_LifeList5"] = $"{I18n.Mail_LifeList5()}%item id (O)431 5 %% [#]{I18n.Mail_LifeList5_Title()}"; + // 7 birds identified, salmonberries + mail["Mods_Ivy_OrnithologistsGuild_LifeList7"] = $"{I18n.Mail_LifeList7()}%item id (O)296 5 %% [#]{I18n.Mail_LifeList7_Title()}"; + // all bird identified, golden egg + mail["Mods_Ivy_OrnithologistsGuild_LifeListAll"] = $"{I18n.Mail_LifeListAll()}%item id (O)928 %% %item conversationTopic Ivy_OrnithologistGuild_LifeListAll 14 %% [#]{I18n.Mail_LifeListAll_Title()}"; + } + + private static void Edit_DataTriggerActions(IAssetData data) + { + string modId = ModEntry.Instance.ModManifest.UniqueID; + var tActs = data.GetData>(); + // send intro mail once, immediately on day start/mod install + tActs.Add(new() + { + Id = $"{modId}_Mail_Introduction", + Trigger = "DayStarted", + Condition = "DATE_RANGE spring 5 1", + Action = "AddMail Current Mods_Ivy_OrnithologistsGuild_Introduction Now", + // set MarkActionApplied=true to do this only once, this is the default value + //MarkActionApplied = true + }); + // send identified count mails at end of day (for tomorrow), when goal is reached + tActs.Add(new() + { + Id = $"{modId}_Mail_LifeList1", + Trigger = "DayEnding", + Condition = "Ivy.OrnithologistsGuild_IDENTIFIED_AT_LEAST 1", + Action = "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeList1", + }); + tActs.Add(new() + { + Id = $"{modId}_Mail_LifeList3", + Trigger = "DayEnding", + Condition = "Ivy.OrnithologistsGuild_IDENTIFIED_AT_LEAST 3", + Action = "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeList3", + }); + tActs.Add(new() + { + Id = $"{modId}_Mail_LifeList5", + Trigger = "DayEnding", + Condition = "Ivy.OrnithologistsGuild_IDENTIFIED_AT_LEAST 5", + Action = "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeList5", + }); + tActs.Add(new() + { + Id = $"{modId}_Mail_LifeList7", + Trigger = "DayEnding", + Condition = "Ivy.OrnithologistsGuild_IDENTIFIED_AT_LEAST 7", + Action = "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeList7", + }); + tActs.Add(new() + { + Id = $"{modId}_Mail_LifeListAll", + Trigger = "DayEnding", + Condition = "Ivy.OrnithologistsGuild_IDENTIFIED_ALL", + Action = "AddMail Current Mods_Ivy_OrnithologistsGuild_LifeListAll", + }); + } + } } diff --git a/OrnithologistsGuild/i18n/default.json b/OrnithologistsGuild/i18n/default.json index 76120cf..cfce88b 100644 --- a/OrnithologistsGuild/i18n/default.json +++ b/OrnithologistsGuild/i18n/default.json @@ -38,5 +38,19 @@ "items.Binoculars.nestStateFledged": "A nest! By the looks of it, the babies recently fledged!", "items.Binoculars.lifeList": "I should open my Life List to read more about them.", "items.AntiqueBinoculars.message": "The ancient binoculars fell apart in your hands.", - "items.JojaBinoculars.message": "The cheaply made binoculars jammed when you tried to focus them." + "items.JojaBinoculars.message": "The cheaply made binoculars jammed when you tried to focus them.", + // mail data, moved from C# + "mail.Introduction": "Dear @, ^^Your grandmother, an avid birder of many years, left you this. We hope you find a way to continue her tradition this spring. ^^Good luck, and watch for bird's nests! ^The Pelican Town Ornithologist's Guild", + "mail.LifeList1": "Dear @, ^^Congrats, you've identified your first bird! We think these may be of some help. ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", + "mail.LifeList3": "Dear @, ^^Three birds identified! You're on a roll. Leave some of this delicious corn for the birds! ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", + "mail.LifeList5": "Dear @, ^^Five birds identified is quite the milestone. If only these Sunflower Seeds were hulled... ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", + "mail.LifeList7": "Dear @, ^^Seven birds identified!? You're becoming an expert! Perhaps the frugivores in your life will enjoy this. ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", + "mail.LifeListAll": "Dear @, ^^You've identified every bird Pelican Town has to offer! Your grandmother left you this as a reward for a job well done. She would be very proud of the birder you've become. < ^^Until next time, ^The Pelican Town Ornithologist's Guild", + // mail titles, appear in the mail collection screen + "mail.Introduction.title": "Ornithologist's Guild: Introduction", + "mail.LifeList1.title": "Ornithologist's Guild: First Bird", + "mail.LifeList3.title": "Ornithologist's Guild: Three Birds", + "mail.LifeList5.title": "Ornithologist's Guild: Five Birds", + "mail.LifeList7.title": "Ornithologist's Guild: Seven Birds", + "mail.LifeListAll.title": "Ornithologist's Guild: All Birds" } \ No newline at end of file From f9cfb568b2240b4abad3a60402f6acf90ad88faa Mon Sep 17 00:00:00 2001 From: mushymato Date: Thu, 21 Nov 2024 18:07:34 -0500 Subject: [PATCH 5/8] fix binoculars draw --- .../ObjectPatches.Binoculars.cs | 76 +++++++++---------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/OrnithologistsGuild/ObjectPatches.Binoculars.cs b/OrnithologistsGuild/ObjectPatches.Binoculars.cs index 43847ef..de81767 100644 --- a/OrnithologistsGuild/ObjectPatches.Binoculars.cs +++ b/OrnithologistsGuild/ObjectPatches.Binoculars.cs @@ -13,7 +13,8 @@ namespace OrnithologistsGuild { - public partial class ObjectPatches { + public partial class ObjectPatches + { private record BincoularsAnimation(int Elapsed, string CurrentToolId); private const int ANIMATE_DURATION = 750; @@ -39,43 +40,39 @@ public static void drawHairAndAccesories_Postfix(FarmerRenderer __instance, Spri var sourceRect = new Rectangle(binoculars.CurrentParentTileIndex * 16, 0, 16, 16); - if (Utilities.TryGetNonPublicFieldValue(__instance, "positionOffset", out Vector2 positionOffset) && - Utilities.TryGetNonPublicFieldValue(__instance, "rotationAdjustment", out Vector2 rotationAdjustment)) + switch (facingDirection) { - switch (facingDirection) - { - case 0: - break; - case 1: - sourceRect.Offset(0, 16); - b.Draw( - binocularsTexture.Value, - position + origin + positionOffset + rotationAdjustment + - new Vector2( - featureXOffsetPerFrame[currentFrame] * 4, - 4 + featureYOffsetPerFrame[currentFrame] * 4 + __instance.heightOffset.Value + 20), - sourceRect, overrideColor, rotation, origin, 4f * scale, SpriteEffects.None, GetLayerDepth(layerDepth, accessoryLayer)); - break; - case 2: - b.Draw( - binocularsTexture.Value, - position + origin + positionOffset + rotationAdjustment + - new Vector2( - featureXOffsetPerFrame[currentFrame] * 4, - 8 + featureYOffsetPerFrame[currentFrame] * 4 + __instance.heightOffset.Value + 24), - sourceRect, overrideColor, rotation, origin, 4f * scale, SpriteEffects.None, GetLayerDepth(layerDepth, accessoryLayer)); - break; - case 3: - sourceRect.Offset(0, 16); - b.Draw( - binocularsTexture.Value, - position + origin + positionOffset + rotationAdjustment + - new Vector2( - -featureXOffsetPerFrame[currentFrame] * 4, - 4 + featureYOffsetPerFrame[currentFrame] * 4 + __instance.heightOffset.Value + 20), - sourceRect, overrideColor, rotation, origin, 4f * scale, SpriteEffects.FlipHorizontally, GetLayerDepth(layerDepth, accessoryLayer)); - break; - } + case 0: + break; + case 1: + sourceRect.Offset(0, 16); + b.Draw( + binocularsTexture.Value, + position + origin + __instance.positionOffset + __instance.rotationAdjustment + + new Vector2( + featureXOffsetPerFrame[currentFrame] * 4, + 4 + featureYOffsetPerFrame[currentFrame] * 4 + __instance.heightOffset.Value + 20), + sourceRect, overrideColor, rotation, origin, 4f * scale, SpriteEffects.None, GetLayerDepth(layerDepth, accessoryLayer)); + break; + case 2: + b.Draw( + binocularsTexture.Value, + position + origin + __instance.positionOffset + __instance.rotationAdjustment + + new Vector2( + featureXOffsetPerFrame[currentFrame] * 4, + 8 + featureYOffsetPerFrame[currentFrame] * 4 + __instance.heightOffset.Value + 24), + sourceRect, overrideColor, rotation, origin, 4f * scale, SpriteEffects.None, GetLayerDepth(layerDepth, accessoryLayer)); + break; + case 3: + sourceRect.Offset(0, 16); + b.Draw( + binocularsTexture.Value, + position + origin + __instance.positionOffset + __instance.rotationAdjustment + + new Vector2( + -featureXOffsetPerFrame[currentFrame] * 4, + 4 + featureYOffsetPerFrame[currentFrame] * 4 + __instance.heightOffset.Value + 20), + sourceRect, overrideColor, rotation, origin, 4f * scale, SpriteEffects.FlipHorizontally, GetLayerDepth(layerDepth, accessoryLayer)); + break; } } } @@ -140,7 +137,7 @@ public static void Farmer_draw_Postfix(Farmer __instance, SpriteBatch b) animation = animation with { Elapsed = animation.Elapsed + Game1.currentGameTime.ElapsedGameTime.Milliseconds }; currentAnimations[__instance.UniqueMultiplayerID] = animation; - + if (animation.CurrentToolId != __instance.CurrentTool?.QualifiedItemId) { // Animation stopped due to switching tools @@ -263,7 +260,8 @@ private static void IdentifyBirdies(GameLocation location, Farmer who, Binocular else if (nest.Stage == NestStage.EggsHatched) lines.Add($"{I18n.Items_Binoculars_NestStateEggsHatched()} {idPart}"); else if (nest.Stage == NestStage.Fledged) lines.Add($"{I18n.Items_Binoculars_NestStateFledged()} {idPart}"); - if (isIdentified) { + if (isIdentified) + { // Birdie identified var contentPack = birdieDef.ContentPackDef.ContentPack; var commonNameString = contentPack.Translation.Get($"birdie.{id}.commonName"); From b4cc1a200a7946265f30a892ddfebe2f415412e2 Mon Sep 17 00:00:00 2001 From: mushymato Date: Thu, 21 Nov 2024 18:21:54 -0500 Subject: [PATCH 6/8] remove some unused items --- OrnithologistsGuild/Utilities/Utilities.cs | 16 ++------------- OrnithologistsGuild/i18n/default.json | 2 +- generate_zip.sh | 24 ---------------------- 3 files changed, 3 insertions(+), 39 deletions(-) delete mode 100755 generate_zip.sh diff --git a/OrnithologistsGuild/Utilities/Utilities.cs b/OrnithologistsGuild/Utilities/Utilities.cs index 9ab5ed3..dc993a9 100644 --- a/OrnithologistsGuild/Utilities/Utilities.cs +++ b/OrnithologistsGuild/Utilities/Utilities.cs @@ -52,7 +52,8 @@ public static string GetLocaleSeparator() { var locale = ModEntry.Instance.Helper.Translation.Locale; return $"{System.Globalization.CultureInfo.GetCultureInfo(locale).TextInfo.ListSeparator} "; - } catch + } + catch { return ", "; } @@ -69,19 +70,6 @@ public static Vector2 XY(Vector3 value) return new Vector2(value.X, value.Y); } - public static bool TryGetNonPublicFieldValue(TInstance instance, string fieldName, out TValue value) - { - FieldInfo privateFieldInfo = typeof(TInstance).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); - if (privateFieldInfo != null) - { - value = (TValue)privateFieldInfo.GetValue(instance); - return true; - } - - value = default; - return false; - } - public static Texture2D CensorTexture(Texture2D texture) { // Get the texture data diff --git a/OrnithologistsGuild/i18n/default.json b/OrnithologistsGuild/i18n/default.json index cfce88b..fbb2c85 100644 --- a/OrnithologistsGuild/i18n/default.json +++ b/OrnithologistsGuild/i18n/default.json @@ -39,7 +39,7 @@ "items.Binoculars.lifeList": "I should open my Life List to read more about them.", "items.AntiqueBinoculars.message": "The ancient binoculars fell apart in your hands.", "items.JojaBinoculars.message": "The cheaply made binoculars jammed when you tried to focus them.", - // mail data, moved from C# + // mail data "mail.Introduction": "Dear @, ^^Your grandmother, an avid birder of many years, left you this. We hope you find a way to continue her tradition this spring. ^^Good luck, and watch for bird's nests! ^The Pelican Town Ornithologist's Guild", "mail.LifeList1": "Dear @, ^^Congrats, you've identified your first bird! We think these may be of some help. ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", "mail.LifeList3": "Dear @, ^^Three birds identified! You're on a roll. Leave some of this delicious corn for the birds! ^^Good luck and happy birding, ^The Pelican Town Ornithologist's Guild", diff --git a/generate_zip.sh b/generate_zip.sh deleted file mode 100755 index 1cd0bd3..0000000 --- a/generate_zip.sh +++ /dev/null @@ -1,24 +0,0 @@ -#/bin/bash - -pwd=$(pwd) - -# # Move release ZIPs -mkdir /tmp/og_release -find ./*/bin/Release -iname '*Ornithologists Guild*.zip' -exec mv "{}" /tmp/og_release \; - -cd /tmp/og_release - -# # Get original filename -fn=$(find . -iname 'O*.zip' -exec echo "{}" \;) - -# # Extract release ZIPs -find . -iname '*.zip' -exec unzip "{}" -d /tmp/og_release \; -rm /tmp/og_release/*.zip -chmod -R 755 . - -# # Copy final zip -zip -r "$fn" ./* -mv "$fn" "$pwd/" - -# # Clean up -rm -rf /tmp/og_release \ No newline at end of file From 607d9386ee2e96a3e025c9deb74cf33924e1a96b Mon Sep 17 00:00:00 2001 From: Ivy Grey Date: Sat, 23 Nov 2024 14:23:17 -0800 Subject: [PATCH 7/8] Address PR review changes --- OrnithologistsGuild/Content/ContentManager.cs | 2 +- OrnithologistsGuild/Game/{GSQ.cs => GameStateQueries.cs} | 6 +++--- OrnithologistsGuild/ModEntry.cs | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) rename OrnithologistsGuild/Game/{GSQ.cs => GameStateQueries.cs} (83%) diff --git a/OrnithologistsGuild/Content/ContentManager.cs b/OrnithologistsGuild/Content/ContentManager.cs index 01c3370..80918b5 100644 --- a/OrnithologistsGuild/Content/ContentManager.cs +++ b/OrnithologistsGuild/Content/ContentManager.cs @@ -48,7 +48,7 @@ private static void Edit_DataMail(IAssetData data) { var mail = data.AsDictionary().Data; // give lifelist - mail["Mods_Ivy_OrnithologistsGuild_Introduction"] = $"{I18n.Mail_Introduction()}%item id (T)Ivy_OrnithologistsGuild_LifeList %% %item conversationTopic Ivy_OrnithologistGuild_Introduction 14 %% [#]{I18n.Mail_Introduction_Title()}"; + mail["Mods_Ivy_OrnithologistsGuild_Introduction"] = $"{I18n.Mail_Introduction()}%item id {Constants.LIFE_LIST_FQID} %% %item conversationTopic Ivy_OrnithologistGuild_Introduction 14 %% [#]{I18n.Mail_Introduction_Title()}"; // 1 bird identified, mixed seeds mail["Mods_Ivy_OrnithologistsGuild_LifeList1"] = $"{I18n.Mail_LifeList1()}%item id (O)770 5 %% [#]{I18n.Mail_LifeList1_Title()}"; // 3 birds identified, corn diff --git a/OrnithologistsGuild/Game/GSQ.cs b/OrnithologistsGuild/Game/GameStateQueries.cs similarity index 83% rename from OrnithologistsGuild/Game/GSQ.cs rename to OrnithologistsGuild/Game/GameStateQueries.cs index fe65aae..aaa16e4 100644 --- a/OrnithologistsGuild/Game/GSQ.cs +++ b/OrnithologistsGuild/Game/GameStateQueries.cs @@ -8,7 +8,7 @@ namespace OrnithologistsGuild /// /// Add game state queries for use in conditions. /// - public static class GSQ + public static class GameStateQueries { private static IMonitor Monitor; @@ -34,7 +34,7 @@ public static bool IDENTIFIED_AT_LEAST(string[] query, GameStateQueryContext con Monitor.Log(error, LogLevel.Error); return false; } - return SaveDataManager.SaveData.ForPlayer(Game1.player.UniqueMultiplayerID).LifeList.IdentifiedCount >= identify; + return (SaveDataManager.SaveData?.ForPlayer(Game1.player.UniqueMultiplayerID).LifeList.IdentifiedCount ?? 0) >= identify; } /// @@ -46,7 +46,7 @@ public static bool IDENTIFIED_AT_LEAST(string[] query, GameStateQueryContext con /// public static bool IDENTIFIED_ALL(string[] query, GameStateQueryContext context) { - return SaveDataManager.SaveData.ForPlayer(Game1.player.UniqueMultiplayerID).LifeList.IdentifiedCount >= ContentPackManager.BirdieDefs.Count; + return (SaveDataManager.SaveData?.ForPlayer(Game1.player.UniqueMultiplayerID).LifeList.IdentifiedCount ?? 0) >= ContentPackManager.BirdieDefs.Count; } } } \ No newline at end of file diff --git a/OrnithologistsGuild/ModEntry.cs b/OrnithologistsGuild/ModEntry.cs index e166d08..2ab3f58 100644 --- a/OrnithologistsGuild/ModEntry.cs +++ b/OrnithologistsGuild/ModEntry.cs @@ -31,7 +31,7 @@ public override void Entry(IModHelper helper) Helper.Events.Input.ButtonPressed += Input_ButtonPressed; SaveDataManager.Initialize(); - GSQ.Initialize(ModManifest.UniqueID, Monitor); + GameStateQueries.Initialize(ModManifest.UniqueID, Monitor); } private void Input_ButtonPressed(object sender, ButtonPressedEventArgs e) @@ -52,7 +52,6 @@ private void GameLoop_SaveLoaded(object sender, SaveLoadedEventArgs e) MigrateLegacyItems(); SaveDataManager.Load(); - // Mail.Initialize(); NestManager.Initialize(); if (ConfigManager.Config.LogMissingBiomes) From 57b621ffd7e07165100a87cdb4433131f34ada91 Mon Sep 17 00:00:00 2001 From: Ivy Grey Date: Sat, 23 Nov 2024 14:28:15 -0800 Subject: [PATCH 8/8] Correct folder names --- OrnithologistsGuild/OrnithologistsGuild.csproj | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/OrnithologistsGuild/OrnithologistsGuild.csproj b/OrnithologistsGuild/OrnithologistsGuild.csproj index b5c221f..fb80120 100644 --- a/OrnithologistsGuild/OrnithologistsGuild.csproj +++ b/OrnithologistsGuild/OrnithologistsGuild.csproj @@ -1,11 +1,11 @@ net6.0 - + /Users/ivy/Applications/Stardew Valley.app/Contents/MacOS OrnithologistsGuild true ThirdParty - + Ornithologists Guild Release;Debug @@ -16,7 +16,8 @@ - +