Пример #1
0
        private static KeyValuePair <StardewObject, int> ChangeBerryBushHarvest(StardewObject item, Vector2 tile, GameLocation location)
        {
            if (item == null || (item.ParentSheetIndex != 296 && item.ParentSheetIndex != 410))
            {
                return(new KeyValuePair <StardewObject, int>(item, 0));
            }

            int expAmount = 0;

            double chance = mod.Config.BerryBushChanceToGetXP / 100.0;

            if (mod.Config.AutomationHarvestsGrantXP && Game1.random.NextDouble() < chance)
            {
                expAmount = mod.Config.BerryBushXPAmount;
            }

            if (mod.Config.BerryBushQuality)
            {
                item.Quality = ForageFantasy.DetermineForageQuality(Game1.player);
            }
            else
            {
                item.Quality = Game1.MasterPlayer.professions.Contains(Farmer.botanist) ? StardewObject.bestQuality : StardewObject.lowQuality;
            }

            return(new KeyValuePair <StardewObject, int>(item, expAmount));
        }
Пример #2
0
 public static void RewardMushroomBoxExp(ForageFantasy mod, Farmer player)
 {
     if (mod.Config.MushroomXPAmount > 0)
     {
         player.gainExperience(2, mod.Config.MushroomXPAmount);
     }
 }
        private static int DetermineTreeQuality(ForageFantasy mod, Tree tree)
        {
            string moddata;

            tree.modData.TryGetValue($"{mod.ModManifest.UniqueID}/treeAge", out moddata);

            if (!string.IsNullOrEmpty(moddata))
            {
                int age = int.Parse(moddata);

                bool useMonths = mod.Config.TapperQualityOptions == 3;

                int timeForLevelUp = useMonths ? 28 : 28 * 4;

                if (age < timeForLevelUp)
                {
                    return(0);
                }
                else if (age < timeForLevelUp * 2)
                {
                    return(1);
                }
                else if (age < timeForLevelUp * 3)
                {
                    return(2);
                }
                else
                {
                    return(4);
                }
            }

            return(0);
        }
Пример #4
0
 public static void RewardTapperExp(ForageFantasy mod, Farmer player)
 {
     if (mod.Config.TapperXPAmount > 0)
     {
         player.gainExperience(2, mod.Config.TapperXPAmount);
     }
 }
Пример #5
0
        public static bool PatchMushroomBoxMachineOutput(ref object __instance)
        {
            try
            {
                if (mod.Config.AutomationHarvestsGrantXP)
                {
                    TapperAndMushroomQualityLogic.RewardMushroomBoxExp(mod);
                }

                var mushroomBox = mod.Helper.Reflection.GetProperty <StardewObject>(__instance, "Machine").GetValue();

                if (!mod.Config.MushroomBoxQuality)
                {
                    mushroomBox.heldObject.Value.quality.Value = 0;
                }
                else
                {
                    mushroomBox.heldObject.Value.quality.Value = ForageFantasy.DetermineForageQuality(Game1.player);
                }

                return(true);
            }
            catch (Exception e)
            {
                mod.ErrorLog("There was an exception in a patch", e);
                return(true);
            }
        }
Пример #6
0
        // reset every end of the day so we don't accidentally save and then permanently edit a crop, if the mod gets uninstalled
        public static void ResetGrapes(ForageFantasy mod)
        {
            if (!Context.IsMainPlayer || !AreGrapeJsonModsInstalled(mod))
            {
                return;
            }

            ReplaceGrapeStarterDrop(398);
        }
        public static void RewardBerryXP(ForageFantasy mod)
        {
            double chance = mod.Config.BerryBushChanceToGetXP / 100.0;

            if (mod.Config.BerryBushXPAmount > 0 && Game1.random.NextDouble() < chance)
            {
                Game1.player.gainExperience(2, mod.Config.BerryBushXPAmount);
            }
        }
Пример #8
0
        public static bool PatchTapperAndMushroomQuality(ref StardewObject __instance, ref Farmer who, ref bool justCheckingForActivity)
        {
            try
            {
                if (!justCheckingForActivity && __instance != null && __instance.minutesUntilReady <= 0 && __instance.heldObject != null && __instance.heldObject.Value != null)
                {
                    if (TapperAndMushroomQualityLogic.IsTapper(__instance))
                    {
                        TapperAndMushroomQualityLogic.RewardTapperExp(mod);

                        if (mod.Config.TapperQualityOptions <= 0 && mod.Config.TapperQualityOptions > 4)
                        {
                            __instance.heldObject.Value.quality.Value = 0;
                            return(true);
                        }

                        TerrainFeature terrain;
                        who.currentLocation.terrainFeatures.TryGetValue(__instance.TileLocation, out terrain);

                        if (terrain != null && terrain is Tree tree)
                        {
                            __instance.heldObject.Value.quality.Value = TapperAndMushroomQualityLogic.DetermineTapperQuality(mod, who, __instance, tree);
                        }
                        else
                        {
                            __instance.heldObject.Value.quality.Value = 0;
                        }

                        return(true);
                    }

                    if (TapperAndMushroomQualityLogic.IsMushroomBox(__instance))
                    {
                        TapperAndMushroomQualityLogic.RewardMushroomBoxExp(mod);

                        if (!mod.Config.MushroomBoxQuality)
                        {
                            __instance.heldObject.Value.quality.Value = 0;
                        }
                        else
                        {
                            __instance.heldObject.Value.quality.Value = ForageFantasy.DetermineForageQuality(who);
                        }

                        return(true);
                    }
                }

                return(true);
            }
            catch (Exception e)
            {
                mod.ErrorLog("There was an exception in a patch", e);
                return(true);
            }
        }
Пример #9
0
        public static void SetDropToNewGrapes(ForageFantasy mod)
        {
            if (!Context.IsMainPlayer || !AreGrapeJsonModsInstalled(mod))
            {
                return;
            }

            if (TryToGetGrapeID(mod, out int res))
            {
                ReplaceGrapeStarterDrop(res);
            }
        }
Пример #10
0
        public static int DetermineTapperQuality(ForageFantasy mod, Farmer player, Tree tree)
        {
            int option = mod.Config.TapperQualityOptions;

            if (option is 1 or 2)
            {
                // has tapper profession or it's not required
                if (!mod.Config.TapperQualityRequiresTapperPerk || player.professions.Contains(Farmer.tapper))
                {
                    return(ForageFantasy.DetermineForageQuality(player, mod.Config.TapperQualityOptions == 1));
                }
            }
Пример #11
0
        private static KeyValuePair <StardewObject, int> ChangeMushroomHarvest(StardewObject item, Vector2 tile, GameLocation location)
        {
            if (item == null)
            {
                return(new KeyValuePair <StardewObject, int>(item, 0));
            }

            int expAmount = mod.Config.AutomationHarvestsGrantXP ? mod.Config.MushroomXPAmount : 0;

            item.Quality = mod.Config.MushroomBoxQuality ? ForageFantasy.DetermineForageQuality(Game1.MasterPlayer) : StardewObject.lowQuality;

            return(new KeyValuePair <StardewObject, int>(item, expAmount));
        }
Пример #12
0
        public static void Setup(ForageFantasy forageFantasy)
        {
            mod = forageFantasy;

            IDeluxeGrabberReduxApi api = mod.Helper.ModRegistry.GetApi <IDeluxeGrabberReduxApi>("ferdaber.DeluxeGrabberRedux");

            if (api == null)
            {
                return;
            }

            api.GetBerryBushHarvest += ChangeBerryBuchHarvest;
            api.GetMushroomHarvest  += ChangeMushroomHarvest;
        }
        public static void IncreaseTreeAge(ForageFantasy mod, Tree tree)
        {
            string moddata;

            tree.modData.TryGetValue($"{mod.ModManifest.UniqueID}/treeAge", out moddata);

            if (!string.IsNullOrEmpty(moddata))
            {
                int age = int.Parse(moddata);
                tree.modData[$"{mod.ModManifest.UniqueID}/treeAge"] = (age + 1).ToString();
            }
            else
            {
                tree.modData[$"{mod.ModManifest.UniqueID}/treeAge"] = 1.ToString();
            }
        }
        public static void VerifyConfigValues(ForageFantasyConfig config, ForageFantasy mod)
        {
            bool invalidConfig = false;

            if (config.TapperQualityOptions < 0 || config.TapperQualityOptions > 4)
            {
                invalidConfig = true;
                config.TapperQualityOptions = 0;
            }

            if (config.BerryBushChanceToGetXP < 0)
            {
                invalidConfig = true;
                config.BerryBushChanceToGetXP = 0;
            }

            if (config.BerryBushChanceToGetXP > 100)
            {
                invalidConfig = true;
                config.BerryBushChanceToGetXP = 100;
            }

            if (config.BerryBushXPAmount < 0)
            {
                invalidConfig            = true;
                config.BerryBushXPAmount = 0;
            }

            if (config.TapperXPAmount < 0)
            {
                invalidConfig         = true;
                config.TapperXPAmount = 0;
            }

            if (config.MushroomXPAmount < 0)
            {
                invalidConfig           = true;
                config.MushroomXPAmount = 0;
            }

            if (invalidConfig)
            {
                mod.DebugLog("At least one config value was out of range and was reset.");
                mod.Helper.WriteConfig(config);
            }
        }
Пример #15
0
        public static void IncreaseTreeAges(ForageFantasy mod)
        {
            if (!Context.IsMainPlayer)
            {
                return;
            }

            foreach (var location in Game1.locations)
            {
                foreach (var terrainfeature in location.terrainFeatures.Pairs)
                {
                    if (terrainfeature.Value is Tree tree)
                    {
                        IncreaseTreeAge(mod, tree);
                    }
                }
            }
        }
Пример #16
0
        public static bool TryAddItemToPlayerInventory_Pre(ref Farmer player, ref Item item, ref StardewObject container)
        {
            try
            {
                if (TapperAndMushroomQualityLogic.IsMushroomBox(container))
                {
                    if (mod.Config.MushroomBoxQuality)
                    {
                        (item as StardewObject).Quality = ForageFantasy.DetermineForageQuality(player);
                    }
                }

                return(true);
            }
            catch (Exception e)
            {
                mod.ErrorLog("There was an exception in a patch", e);
                return(true);
            }
        }
Пример #17
0
        private static bool TryToGetGrapeID(ForageFantasy mod, out int id)
        {
            if (!AreGrapeJsonModsInstalled(mod))
            {
                id = 0;
                return(false);
            }

            var api = mod.Helper.ModRegistry.GetApi <IJsonAssetsApi>("spacechase0.JsonAssets");

            if (api == null)
            {
                id = 0;
                return(false);
            }

            id = api.GetObjectId("Fine Grape");

            return(true);
        }
        public static void ChangeBundle(ForageFantasy mod)
        {
            if (!mod.Config.CommonFiddleheadFern)
            {
                return;
            }

            Dictionary <string, string> bundleData = Game1.netWorldState.Value.BundleData;

            // Summer Foraging
            string key = "Crafts Room/14";

            string[] bundle = bundleData[key].Split('/');

            if (!bundle[2].Contains("259 1 0"))
            {
                bundle[2] += " 259 1 0";
            }

            bundleData[key] = string.Join("/", bundle);
        }
        public static int DetermineTapperQuality(ForageFantasy mod, Farmer player, StardewObject o, Tree tree)
        {
            int option = mod.Config.TapperQualityOptions;

            if (option == 1 || option == 2)
            {
                // has tapper profession or it's not required
                if (!mod.Config.TapperQualityRequiresTapperPerk || player.professions.Contains(Farmer.tapper))
                {
                    return(ForageFantasy.DetermineForageQuality(player, mod.Config.TapperQualityOptions == 1));
                }
            }
            else if (option == 3 || option == 4)
            {
                // quality increase once a year
                return(DetermineTreeQuality(mod, tree));
            }

            // tapper perk required but doesn't have it or invalid option
            return(0);
        }
Пример #20
0
        public static void ChangeBerryQualityAndGiveExp(Bush bush, ForageFantasy mod)
        {
            int shakeOff;

            string season = (bush.overrideSeason.Value == -1) ? Game1.GetSeasonForLocation(bush.currentLocation) : Utility.getSeasonNameFromNumber(bush.overrideSeason.Value);

            switch (season)
            {
            case "spring":
                shakeOff = 296;
                break;

            case "fall":
                shakeOff = 410;
                break;

            default:
                return;
            }

            bool gaveExp = false;

            foreach (var item in bush.currentLocation.debris)
            {
                if (item?.item?.ParentSheetIndex == shakeOff)
                {
                    if (!gaveExp)
                    {
                        gaveExp = true;
                        RewardBerryXP(mod);
                    }

                    if (mod.Config.BerryBushQuality)
                    {
                        ((StardewObject)item.item).Quality = ForageFantasy.DetermineForageQuality(Game1.player);
                    }
                }
            }
        }
Пример #21
0
        public static void Setup(ForageFantasy forageFantasy)
        {
            mod = forageFantasy;

            IDeluxeGrabberReduxApi api = mod.Helper.ModRegistry.GetApi <IDeluxeGrabberReduxApi>("ferdaber.DeluxeGrabberRedux");

            if (api == null)
            {
                return;
            }

            // if neither is on, we can skip adding our overwrite for better compatibility with other mods
            if ((mod.Config.AutomationHarvestsGrantXP && mod.Config.BerryBushXPAmount > 0 && mod.Config.BerryBushChanceToGetXP > 0) || mod.Config.BerryBushQuality)
            {
                api.GetBerryBushHarvest += ChangeBerryBushHarvest;
            }

            // if neither is on, we can skip adding our overwrite for better compatibility with other mods
            if ((mod.Config.AutomationHarvestsGrantXP && mod.Config.MushroomXPAmount > 0) || mod.Config.MushroomBoxQuality)
            {
                api.GetMushroomHarvest += ChangeMushroomHarvest;
            }
        }
        public static void SetUpModConfigMenu(ForageFantasyConfig config, ForageFantasy mod)
        {
            GenericModConfigMenuAPI api = mod.Helper.ModRegistry.GetApi <GenericModConfigMenuAPI>("spacechase0.GenericModConfigMenu");

            if (api == null)
            {
                return;
            }

            var manifest = mod.ModManifest;

            api.RegisterModConfig(manifest, () => config = new ForageFantasyConfig(), delegate { mod.Helper.WriteConfig(config); VerifyConfigValues(config, mod); });

            api.RegisterLabel(manifest, "Quality Tweaks", null);

            api.RegisterSimpleOption(manifest, "Berry Bush Quality", "Salmonberries and blackberries have quality based\non forage level even without botanist perk.", () => config.BerryBushQuality, (bool val) => config.BerryBushQuality = val);
            api.RegisterSimpleOption(manifest, "Mushroom Box Quality", "Mushrooms have quality based on forage level and botanist perk.", () => config.MushroomBoxQuality, (bool val) => config.MushroomBoxQuality = val);
            api.RegisterChoiceOption(manifest, "Tapper Quality Options", null, () => GetElementFromConfig(TQChoices, config.TapperQualityOptions), (string val) => config.TapperQualityOptions = GetIndexFromArrayElement(TQChoices, val), TQChoices);
            api.RegisterSimpleOption(manifest, "Tapper Perk Is Required", null, () => config.TapperQualityRequiresTapperPerk, (bool val) => config.TapperQualityRequiresTapperPerk             = val);

            api.RegisterLabel(manifest, "XP Rewards", null);

            api.RegisterClampedOption(manifest, "Berry Bush Chance To Get XP", "Chance to get foraging experience when harvesting bushes.\nSet to 0 to disable feature.", () => config.BerryBushChanceToGetXP, (int val) => config.BerryBushChanceToGetXP = val, 0, 100);
            api.RegisterSimpleOption(manifest, "Berry Bush XP Amount", "Amount of XP gained per bush. For reference:\nChopping down a tree is 12XP, a foraging good is 7XP\nNegative values will be reset to 0.", () => config.BerryBushXPAmount, (int val) => config.BerryBushXPAmount = val);
            api.RegisterSimpleOption(manifest, "Mushroom Box XP Amount", "For reference:\nChopping down a tree is 12XP, a foraging good is 7XP\nNegative values will be reset to 0.", () => config.MushroomXPAmount, (int val) => config.MushroomXPAmount = val);
            api.RegisterSimpleOption(manifest, "Tapper XP Amount", "For reference:\nChopping down a tree is 12XP, a foraging good is 7XP\nNegative values will be reset to 0.", () => config.TapperXPAmount, (int val) => config.TapperXPAmount           = val);
            api.RegisterSimpleOption(manifest, "Automation Harvests Grant XP", "Whether automatic harvests with the Automate, Deluxe\nGrabber Redux or One Click Shed Reloader should grant XP.\nKeep in mind that some of those only affect the host.", () => config.AutomationHarvestsGrantXP, (bool val) => config.AutomationHarvestsGrantXP = val);

            api.RegisterLabel(manifest, "Other Features", null);

            api.RegisterSimpleOption(manifest, "Common Fiddlehead Fern¹", "Fiddlehead fern is available outside of the secret forest\nand added to the wild seeds pack and summer foraging bundle.", () => config.CommonFiddleheadFern, (bool val) => config.CommonFiddleheadFern = val);
            api.RegisterSimpleOption(manifest, "Forage Survival Burger¹", "Forage based early game crafting recipes\nand even more efficient cooking recipes.", () => config.ForageSurvivalBurger, (bool val) => config.ForageSurvivalBurger = val);

            // this is a spacer
            api.RegisterLabel(manifest, string.Empty, null);
            api.RegisterLabel(manifest, "1: Restart Needed For Changes To Take Effect", null);
        }
Пример #23
0
        public static void SetUpModConfigMenu(ForageFantasyConfig config, ForageFantasy mod)
        {
            IGenericModConfigMenuApi api = mod.Helper.ModRegistry.GetApi <IGenericModConfigMenuApi>("spacechase0.GenericModConfigMenu");

            if (api == null)
            {
                return;
            }

            var manifest = mod.ModManifest;

            api.RegisterModConfig(
                manifest,
                delegate
            {
                // if the world is ready, then we are not in the main menu, so reset should only reset the keybindings and calendar
                if (Context.IsWorldReady)
                {
                    config.TreeMenuKey            = TreeMenuKeyDefault;
                    config.MushroomTapperCalendar = false;
                }
                else
                {
                    config = new ForageFantasyConfig();
                }
            },
                delegate
            {
                mod.Helper.WriteConfig(config);
                VerifyConfigValues(config, mod);
            }
                );

            api.SetTitleScreenOnlyForNextOptions(manifest, true);

            api.RegisterLabel(manifest, "Quality Tweaks", null);

            if (mod.Helper.ModRegistry.IsLoaded("thelion.AwesomeProfessions"))
            {
                api.RegisterLabel(manifest, "Berry Bush Quality Disabled (Walk Of Life)", null);
                api.RegisterLabel(manifest, "Mushroom Box Quality Disabled (Walk Of Life)", null);
            }
            else
            {
                api.RegisterSimpleOption(manifest, "Berry Bush Quality", "Salmonberries and blackberries have quality based\non forage level even without botanist perk.", () => config.BerryBushQuality, (bool val) => config.BerryBushQuality = val);
                api.RegisterSimpleOption(manifest, "Mushroom Box Quality", "Mushrooms have quality based on forage level and botanist perk.", () => config.MushroomBoxQuality, (bool val) => config.MushroomBoxQuality = val);
            }

            api.RegisterChoiceOption(manifest, "Tapper Quality Options", null, () => GetElementFromConfig(TQChoices, config.TapperQualityOptions), (string val) => config.TapperQualityOptions = GetIndexFromArrayElement(TQChoices, val), TQChoices);
            api.RegisterSimpleOption(manifest, "Tapper Perk Is Required", null, () => config.TapperQualityRequiresTapperPerk, (bool val) => config.TapperQualityRequiresTapperPerk             = val);

            api.RegisterLabel(manifest, "XP Rewards", null);

            api.RegisterClampedOption(manifest, "Berry Bush Chance To Get XP", "Chance to get foraging experience when harvesting bushes.\nSet to 0 to disable feature.", () => config.BerryBushChanceToGetXP, (int val) => config.BerryBushChanceToGetXP = val, 0, 100);
            api.RegisterSimpleOption(manifest, "Berry Bush XP Amount", "Amount of XP gained per bush. For reference:\nChopping down a tree is 12XP, a foraging good is 7XP\nNegative values will be reset to 0.", () => config.BerryBushXPAmount, (int val) => config.BerryBushXPAmount = val);
            api.RegisterSimpleOption(manifest, "Mushroom Box XP Amount", "For reference:\nChopping down a tree is 12XP, a foraging good is 7XP\nNegative values will be reset to 0.", () => config.MushroomXPAmount, (int val) => config.MushroomXPAmount = val);
            api.RegisterSimpleOption(manifest, "Tapper XP Amount", "For reference:\nChopping down a tree is 12XP, a foraging good is 7XP\nNegative values will be reset to 0.", () => config.TapperXPAmount, (int val) => config.TapperXPAmount           = val);
            api.RegisterSimpleOption(manifest, "Automation Harvests Grant XP", "Whether automatic harvests with the Automate, Deluxe\nGrabber Redux or One Click Shed Reloader should grant XP.\nKeep in mind that some of those only affect the host.", () => config.AutomationHarvestsGrantXP, (bool val) => config.AutomationHarvestsGrantXP = val);

            api.RegisterLabel(manifest, "Tapper Days Needed Changes", null);

            api.RegisterSimpleOption(manifest, "Days Needed Changes Enabled", "If this is disabled, then all features\nin this category don't do anything", () => config.TapperDaysNeededChangesEnabled, (bool val) => config.TapperDaysNeededChangesEnabled = val);
            api.RegisterSimpleOption(manifest, "Maple Tree Days Needed", "default: 9 days, recommended: 7 days", () => config.MapleDaysNeeded, (int val) => config.MapleDaysNeeded = val);
            api.RegisterSimpleOption(manifest, "Oak Tree Days Needed", "default: 7 days, recommended: 7 days", () => config.OakDaysNeeded, (int val) => config.OakDaysNeeded       = val);
            api.RegisterSimpleOption(manifest, "Pine Tree Days Needed", "default: 5 days, recommended: 7 days", () => config.PineDaysNeeded, (int val) => config.PineDaysNeeded    = val);
            api.RegisterSimpleOption(manifest, "Mushroom Tree Heavy Tapper Fix", null, () => config.MushroomTreeHeavyTappersFix, (bool val) => config.MushroomTreeHeavyTappersFix  = val);
            api.RegisterSimpleOption(manifest, "Mushroom Tree Tapper\nConsistency Change", null, () => config.MushroomTreeTappersConsistencyChange, (bool val) => config.MushroomTreeTappersConsistencyChange = val);

            api.RegisterLabel(manifest, "Other Features", null);

            api.RegisterSimpleOption(manifest, "Mushroom Tree Seeds Drop", null, () => config.MushroomTreeSeedsDrop, (bool val) => config.MushroomTreeSeedsDrop = val);
            api.RegisterSimpleOption(manifest, "Common Fiddlehead Fern", "Fiddlehead fern is available outside of the secret forest\nand added to the wild seeds pack and summer foraging bundle.", () => config.CommonFiddleheadFern, (bool val) => config.CommonFiddleheadFern = val);
            api.RegisterSimpleOption(manifest, "Forage Survival Burger", "Forage based early game crafting recipes\nand even more efficient cooking recipes.", () => config.ForageSurvivalBurger, (bool val) => config.ForageSurvivalBurger = val);

            api.SetTitleScreenOnlyForNextOptions(manifest, false);

            api.RegisterSimpleOption(manifest, "Mushroom Tapper Calendar", null, () => config.MushroomTapperCalendar, (bool val) => config.MushroomTapperCalendar = val);

            api.AddKeybindList(manifest, () => config.TreeMenuKey, (KeybindList keybindList) => config.TreeMenuKey = keybindList, () => "Tree Menu Key");

            api.SetTitleScreenOnlyForNextOptions(manifest, true);

            if (GrapeLogic.AreGrapeJsonModsInstalled(mod))
            {
                api.RegisterLabel(manifest, "Fine Grapes Feature Installed And Enabled", "Remove the Json Assets mod pack to disable this option");
            }
        }
Пример #24
0
        public static void VerifyConfigValues(ForageFantasyConfig config, ForageFantasy mod)
        {
            bool invalidConfig = false;

            if (config.MapleDaysNeeded <= 0)
            {
                invalidConfig          = true;
                config.MapleDaysNeeded = 1;
            }

            if (config.PineDaysNeeded <= 0)
            {
                invalidConfig         = true;
                config.PineDaysNeeded = 1;
            }

            if (config.OakDaysNeeded <= 0)
            {
                invalidConfig        = true;
                config.OakDaysNeeded = 1;
            }

            if (config.TapperQualityOptions < 0 || config.TapperQualityOptions > 4)
            {
                invalidConfig = true;
                config.TapperQualityOptions = 0;
            }

            if (config.BerryBushChanceToGetXP < 0)
            {
                invalidConfig = true;
                config.BerryBushChanceToGetXP = 0;
            }

            if (config.BerryBushChanceToGetXP > 100)
            {
                invalidConfig = true;
                config.BerryBushChanceToGetXP = 100;
            }

            if (config.BerryBushXPAmount < 0)
            {
                invalidConfig            = true;
                config.BerryBushXPAmount = 0;
            }

            if (config.TapperXPAmount < 0)
            {
                invalidConfig         = true;
                config.TapperXPAmount = 0;
            }

            if (config.MushroomXPAmount < 0)
            {
                invalidConfig           = true;
                config.MushroomXPAmount = 0;
            }

            if (mod.Helper.ModRegistry.IsLoaded("thelion.AwesomeProfessions"))
            {
                if (config.MushroomBoxQuality || config.BerryBushQuality)
                {
                    invalidConfig = true;

                    config.MushroomBoxQuality = false;
                    config.BerryBushQuality   = false;

                    mod.DebugLog("Enabled Walk of Life compatibility.");
                }
            }

            try
            {
                // CommonFiddleheadFern and ForageSurvivalBurger
                mod.Helper.Content.InvalidateCache("Data/CraftingRecipes");

                // CommonFiddleheadFern
                mod.Helper.Content.InvalidateCache("Data/Locations");

                // ForageSurvivalBurger
                mod.Helper.Content.InvalidateCache("Data/CookingRecipes");

                // Tapper days needed changes
                mod.Helper.Content.InvalidateCache("Data/ObjectInformation");
            }
            catch (Exception e)
            {
                mod.DebugLog($"Exception when trying to invalidate cache on config change {e}");
            }

            if (invalidConfig)
            {
                mod.DebugLog("At least one config value was out of range and was reset.");
                mod.Helper.WriteConfig(config);
            }
        }
        public static void TestValues(ForageFantasy mod, bool showOnlyTotals, bool ignoreSecretForest)
        {
            List <string> seasons = new List <string>()
            {
                "summer"
            };                                                      ////, "spring", "fall", "winter" };

            foreach (var season in seasons)
            {
                int[][] results = new int[7][];
                for (int i = 0; i < results.Length; i++)
                {
                    results[i] = new int[1000];
                }

                foreach (var loc in Game1.locations)
                {
                    Random r = new Random(((int)Game1.uniqueIDForThisGame / 2) + (int)Game1.stats.DaysPlayed);
                    Dictionary <string, string> locationData = Game1.content.Load <Dictionary <string, string> >("Data/Locations");

                    int id = -1;
                    switch (loc.name)
                    {
                    case "BusStop":
                        id = 0;
                        break;

                    case "Forest":

                        id = 1;
                        break;

                    case "Mountain":

                        id = 2;
                        break;

                    case "Railroad":

                        id = 3;
                        break;

                    case "Woods":
                        if (ignoreSecretForest)
                        {
                            continue;
                        }

                        id = 4;
                        break;

                    case "Town":
                        id = 5;
                        break;

                    case "Backwoods":
                        id = 6;
                        break;

                    default:
                        continue;
                    }

                    if (locationData.ContainsKey(loc.name))
                    {
                        string rawData = locationData[loc.name].Split(new char[]
                        {
                            '/'
                        })[Utility.getSeasonNumber(season)];
                        //// && loc.numberOfSpawnedObjectsOnMap < 6)
                        if (!rawData.Equals("-1"))
                        {
                            string[] split = rawData.Split(new char[]
                            {
                                ' '
                            });
                            int numberToSpawn = 100000;
                            for (int i = 0; i < numberToSpawn; i++)
                            {
                                int     xCoord   = r.Next(loc.map.DisplayWidth / 64);
                                int     yCoord   = r.Next(loc.map.DisplayHeight / 64);
                                Vector2 location = new Vector2((float)xCoord, (float)yCoord);
                                StardewValley.Object o;
                                loc.objects.TryGetValue(location, out o);
                                int whichObject = r.Next(split.Length / 2) * 2;
                                if (r.NextDouble() < Convert.ToDouble(split[whichObject + 1], CultureInfo.InvariantCulture))
                                {
                                    o = new StardewValley.Object(location, Convert.ToInt32(split[whichObject]), null, false, true, false, true);
                                    results[id][o.ParentSheetIndex]++;
                                }
                            }
                        }
                    }
                }

                int[] totals = new int[1000];

                float totaltotal = 0;
                for (int j = 0; j < results.Length; j++)
                {
                    if (j == 4 && ignoreSecretForest)
                    {
                        continue;
                    }

                    string s = string.Empty;
                    switch (j)
                    {
                    case 0:
                        s += "BusStop";
                        break;

                    case 1:
                        s += "Forest";
                        break;

                    case 2:
                        s += "Mountain";
                        break;

                    case 3:
                        s += "Railroad";
                        break;

                    case 4:
                        s += "Woods";
                        break;

                    case 5:
                        s += "Town";
                        break;

                    case 6:
                        s += "Backwoods";
                        break;
                    }

                    float total = 0;
                    for (int i = 0; i < results[j].Length; i++)
                    {
                        total += results[j][i];
                    }

                    totaltotal += total;
                    s          += $"({total} items)";

                    if (!showOnlyTotals)
                    {
                        mod.DebugLog(s);
                        mod.DebugLog(string.Empty);
                    }

                    for (int i = 0; i < results[j].Length; i++)
                    {
                        if (results[j][i] > 0)
                        {
                            var o = new StardewValley.Object(new Vector2(0, 0), i, null, false, true, false, true);

                            int    number           = results[j][i];
                            float  percentage       = number / total;
                            string percentageString = percentage.ToString("P", CultureInfo.InvariantCulture);
                            if (!showOnlyTotals)
                            {
                                mod.DebugLog($"{o.DisplayName}: {number}, {percentageString}");
                            }
                        }

                        totals[i] += results[j][i];
                    }

                    if (!showOnlyTotals)
                    {
                        mod.DebugLog(string.Empty);
                    }
                }

                mod.DebugLog($"Total ({totaltotal} items)");

                mod.DebugLog(string.Empty);

                for (int i = 0; i < totals.Length; i++)
                {
                    if (totals[i] > 0)
                    {
                        var o = new StardewValley.Object(new Vector2(0, 0), i, null, false, true, false, true);

                        int    number           = totals[i];
                        float  percentage       = number / totaltotal;
                        string percentageString = percentage.ToString("P", CultureInfo.InvariantCulture);
                        mod.DebugLog($"{o.DisplayName}: {number}, {percentageString}");
                    }
                }

                mod.DebugLog(string.Empty);
            }
        }
Пример #26
0
        public static void Edit <T>(IAssetData asset, ForageFantasy mod)
        {
            if (mod.Config.TapperDaysNeededChangesEnabled && asset.AssetNameEquals("Data/ObjectInformation"))
            {
                /*  here is the reasoning for the math
                 *
                 *  normal tapper:
                 *  maple syrup 9 days 200g
                 *  oak resin 7 days 150g
                 *  pine tar 5 days 100g
                 *
                 *  so 22,2g per day, 21,4g per day, 20g per day
                 *
                 *  heavy tapper:
                 *  maple syrup 4 days 200g
                 *  oak resin 3 days 150g
                 *  pine tar 2 days 100g
                 *
                 *  so 50g per day for all of them
                 *
                 *  ----
                 *
                 *  wanted values:
                 *  maple syrup 7 days 150g
                 *  oak resin 7 days 150g
                 *  pine tar 7 days 150g
                 *
                 *  so the calculation is:
                 *  newSellPrice = (int)Math.Round(daysNeeded * (150f / 7f), MidpointRounding.AwayFromZero);
                 */

                IDictionary <int, string> data = asset.AsDictionary <int, string>().Data;

                var priceChanges = new Dictionary <int, int>()
                {
                    { 724, mod.Config.MapleDaysNeeded }, { 725, mod.Config.OakDaysNeeded }, { 726, mod.Config.PineDaysNeeded }
                };

                foreach (var item in priceChanges)
                {
                    var entry    = data[item.Key];
                    var fields   = entry.Split('/');
                    var newPrice = TapperAndMushroomQualityLogic.GetTapperProductValueForDaysNeeded(item.Value);
                    fields[1]      = newPrice.ToString();
                    data[item.Key] = string.Join("/", fields);
                }
            }

            if (mod.Config.CommonFiddleheadFern)
            {
                if (asset.AssetNameEquals("Data/CraftingRecipes"))
                {
                    IDictionary <string, string> data = asset.AsDictionary <string, string>().Data;

                    var entry  = data["Wild Seeds (Su)"];
                    var fields = entry.Split('/');
                    fields[0] = "396 1 398 1 402 1 259 1";
                    data["Wild Seeds (Su)"] = string.Join("/", fields);
                }

                if (asset.AssetNameEquals("Data/Locations"))
                {
                    IDictionary <string, string> data = asset.AsDictionary <string, string>().Data;

                    var keys = data.Keys.ToList();

                    for (int i = 0; i < keys.Count; i++)
                    {
                        string   location = keys[i];
                        string[] fields   = data[location].Split('/');

                        switch (location)
                        {
                        case "BusStop":
                            fields[1] = "396 .6 398 .6 402 .6";
                            break;

                        case "Forest":
                            fields[1] = "396 .8 398 .8 259 .8";
                            break;

                        case "Mountain":
                            fields[1] = "396 .7 398 .7 259 .8";
                            break;

                        case "Backwoods":
                            fields[1] = "396 .7 398 .7 259 .8";
                            break;

                        case "Railroad":
                            fields[1] = "396 .6 398 .6 402 .6";
                            break;

                        case "Woods":
                            fields[1] = "259 .7 420 .7";
                            break;
                        }

                        data[location] = string.Join("/", fields);
                    }
                }
            }

            if (mod.Config.ForageSurvivalBurger)
            {
                var spring = mod.Helper.Translation.Get("SpringBurger");
                var summer = mod.Helper.Translation.Get("SummerBurger");
                var fall   = mod.Helper.Translation.Get("FallBurger");
                var winter = mod.Helper.Translation.Get("WinterBurger");

                if (asset.AssetNameEquals("Data/CookingRecipes"))
                {
                    IDictionary <string, string> data = asset.AsDictionary <string, string>().Data;

                    data.Remove("Survival Burger");
                    data.Add("Survival Burger (Sp)", $"216 1 16 1 20 1 22 1/70 1/241 2/s Foraging 2/{spring}");
                    data.Add("Survival Burger (Su)", $"216 1 398 1 396 1 259 1/70 1/241 2/s Foraging 2/{summer}");
                    data.Add("Survival Burger (Fa)", $"216 1 404 1 406 1 408 1/70 1/241 2/s Foraging 2/{fall}");
                    data.Add("Survival Burger (Wi)", $"216 1 412 1 414 1 416 1/70 1/241 2/s Foraging 2/{winter}");
                }

                if (asset.AssetNameEquals("Data/CraftingRecipes"))
                {
                    IDictionary <string, string> data = asset.AsDictionary <string, string>().Data;

                    data.Add("Survival Burger (Sp)", $"216 1 16 1 20 1 22 1/Field/241/false/s Foraging 2/{spring}");
                    data.Add("Survival Burger (Su)", $"216 1 398 1 396 1 259 1/Field/241/false/s Foraging 2/{summer}");
                    data.Add("Survival Burger (Fa)", $"216 1 404 1 406 1 408 1/Field/241/false/s Foraging 2/{fall}");
                    data.Add("Survival Burger (Wi)", $"216 1 412 1 414 1 416 1/Field/241/false/s Foraging 2/{winter}");
                }
            }
        }
Пример #27
0
        public static void PatchAll(ForageFantasy forageFantasy)
        {
            mod = forageFantasy;

            var harmony = new Harmony(mod.ModManifest.UniqueID);

            try
            {
                harmony.Patch(
                    original: AccessTools.Method(typeof(StardewObject), "checkForAction"),
                    prefix: new HarmonyMethod(typeof(Patcher), nameof(PatchTapperAndMushroomQuality)));

                harmony.Patch(
                    original: AccessTools.Method(typeof(Crop), "getRandomWildCropForSeason"),
                    prefix: new HarmonyMethod(typeof(Patcher), nameof(PatchSummerWildSeedResult)));

                harmony.Patch(
                    original: AccessTools.Method(typeof(Bush), "shake"),
                    prefix: new HarmonyMethod(typeof(Patcher), nameof(DetectHarvestableBerryBush)));

                harmony.Patch(
                    original: AccessTools.Method(typeof(Bush), "shake"),
                    postfix: new HarmonyMethod(typeof(Patcher), nameof(FixBerryQuality)));

                harmony.Patch(
                    original: AccessTools.Method(typeof(Tree), nameof(Tree.UpdateTapperProduct)),
                    postfix: new HarmonyMethod(typeof(Patcher), nameof(UpdateTapperProduct_Post)));

                harmony.Patch(
                    original: AccessTools.Method(typeof(Tree), "shake"),
                    prefix: new HarmonyMethod(typeof(Patcher), nameof(ShakeTree)));

                harmony.Patch(
                    original: AccessTools.Method(typeof(Tree), "performSeedDestroy"),
                    prefix: new HarmonyMethod(typeof(Patcher), nameof(PerformSeedDestroy)));

                harmony.Patch(
                    original: AccessTools.Method(typeof(Billboard), nameof(Billboard.draw), new Type[] { typeof(SpriteBatch) }),
                    postfix: new HarmonyMethod(typeof(Patcher), nameof(Draw_Postfix)));
            }
            catch (Exception e)
            {
                mod.ErrorLog("Error while trying to setup required patches:", e);
            }

            if (mod.Helper.ModRegistry.IsLoaded("Pathoschild.Automate"))
            {
                try
                {
                    mod.DebugLog("This mod patches Automate. If you notice issues with Automate, make sure it happens without this mod before reporting it to the Automate page.");

                    // I don't see a use in using MachineWrapper because it's also internal I need to check for the type of the machine anyway which would be way too much reflection at runtime
                    var mushroomBox = AccessTools.TypeByName("Pathoschild.Stardew.Automate.Framework.Machines.Objects.MushroomBoxMachine");
                    var tapper      = AccessTools.TypeByName("Pathoschild.Stardew.Automate.Framework.Machines.Objects.TapperMachine");
                    var berryBush   = AccessTools.TypeByName("Pathoschild.Stardew.Automate.Framework.Machines.TerrainFeatures.BushMachine");

                    harmony.Patch(
                        original: AccessTools.Method(tapper, "GetOutput"),
                        prefix: new HarmonyMethod(typeof(Patcher), nameof(PatchTapperMachineOutput)));

                    harmony.Patch(
                        original: AccessTools.Method(mushroomBox, "GetOutput"),
                        prefix: new HarmonyMethod(typeof(Patcher), nameof(PatchMushroomBoxMachineOutput)));

                    harmony.Patch(
                        original: AccessTools.Method(berryBush, "GetOutput"),
                        postfix: new HarmonyMethod(typeof(Patcher), nameof(PatchPostBushMachineXP)));
                }
                catch (Exception e)
                {
                    mod.ErrorLog($"Error while trying to patch Automate. Please report this to the mod page of {mod.ModManifest.Name}, not Automate:", e);
                }
            }

            if (mod.Helper.ModRegistry.IsLoaded("BitwiseJonMods.OneClickShedReloader"))
            {
                try
                {
                    mod.DebugLog("This mod patches OneClickShedReloader. If you notice issues with OneClickShedReloader, make sure it happens without this mod before reporting it to the OneClickShedReloader page.");

                    var handler = AccessTools.TypeByName("BitwiseJonMods.BuildingContentsHandler");
                    var entry   = AccessTools.TypeByName("BitwiseJonMods.ModEntry");

                    harmony.Patch(
                        original: AccessTools.Method(handler, "TryAddItemToPlayerInventory"),
                        prefix: new HarmonyMethod(typeof(Patcher), nameof(TryAddItemToPlayerInventory_Pre)));

                    harmony.Patch(
                        original: AccessTools.Method(handler, "TryAddItemToPlayerInventory"),
                        postfix: new HarmonyMethod(typeof(Patcher), nameof(TryAddItemToPlayerInventory_Post)));

                    harmony.Patch(
                        original: AccessTools.Method(entry, "HarvestAllItemsInBuilding"),
                        postfix: new HarmonyMethod(typeof(Patcher), nameof(ReduceQualityAfterHarvest)));
                }
                catch (Exception e)
                {
                    mod.ErrorLog($"Error while trying to patch OneClickShedReloader. Please report this to the mod page of {mod.ModManifest.Name}, not OneClickShedReloader:", e);
                }
            }

            /* // in case I want this at some point
             * foreach (var method in Harmony.GetAllPatchedMethods())
             * {
             *  var patches = Harmony.GetPatchInfo(method);
             *
             *  foreach (var patch in patches.Prefixes)
             *  {
             *      if (patch.owner == mod.ModManifest.UniqueID)
             *      {
             *          mod.TraceLog($"method: {method.Name} prefix: {patch.PatchMethod.Name}");
             *      }
             *  }
             *
             *  foreach (var patch in patches.Postfixes)
             *  {
             *      if (patch.owner == mod.ModManifest.UniqueID)
             *      {
             *          mod.TraceLog($"method: {method.Name} postfix: {patch.PatchMethod.Name}");
             *      }
             *  }
             *
             *  foreach (var patch in patches.Transpilers)
             *  {
             *      if (patch.owner == mod.ModManifest.UniqueID)
             *      {
             *          mod.TraceLog($"method: {method.Name} transpiler: {patch.PatchMethod.Name}");
             *      }
             *  }
             * }
             */
        }
Пример #28
0
 public TreeMenu(ForageFantasy mod, TerrainFeature tree)
     : base(TreeTypeToName(tree))
 {
     this.mod  = mod;
     this.tree = tree;
 }
Пример #29
0
        public static void PatchAll(ForageFantasy forageFantasy)
        {
            mod = forageFantasy;

            var harmony = HarmonyInstance.Create(mod.ModManifest.UniqueID);

            try
            {
                harmony.Patch(
                    original: AccessTools.Method(typeof(StardewObject), "checkForAction"),
                    prefix: new HarmonyMethod(typeof(Patcher), nameof(PatchTapperAndMushroomQuality))
                    );

                harmony.Patch(
                    original: AccessTools.Method(typeof(Crop), "getRandomWildCropForSeason"),
                    prefix: new HarmonyMethod(typeof(Patcher), nameof(PatchSummerWildSeedResult))
                    );

                harmony.Patch(
                    original: AccessTools.Method(typeof(Bush), "shake"),
                    prefix: new HarmonyMethod(typeof(Patcher), nameof(DetectHarvestableBerryBush))
                    );

                harmony.Patch(
                    original: AccessTools.Method(typeof(Bush), "shake"),
                    postfix: new HarmonyMethod(typeof(Patcher), nameof(FixBerryQuality))
                    );
            }
            catch (Exception e)
            {
                mod.ErrorLog("Error while trying to setup required patches:", e);
            }

            if (mod.Helper.ModRegistry.IsLoaded("Pathoschild.Automate"))
            {
                try
                {
                    mod.DebugLog("This mod patches Automate. If you notice issues with Automate, make sure it happens without this mod before reporting it to the Automate page.");

                    // this is so ugly but I can't include a reference
                    Assembly assembly = null;

                    foreach (var item in AppDomain.CurrentDomain.GetAssemblies())
                    {
                        if (item.GetName().Name.Trim() == "Automate")
                        {
                            assembly = item;
                            break;
                        }
                    }

                    if (assembly == null)
                    {
                        mod.ErrorLog($"Error while trying to patch Automate. Please report this to the mod page of {mod.ModManifest.Name}, not Automate.");
                        return;
                    }

                    // I don't see a use in using MachineWrapper because it's also internal I need to check for the type of the machine anyway which would be way too much reflection at runtime
                    var mushroomBox = assembly.GetType("Pathoschild.Stardew.Automate.Framework.Machines.Objects.MushroomBoxMachine");
                    var tapper      = assembly.GetType("Pathoschild.Stardew.Automate.Framework.Machines.Objects.TapperMachine");
                    var berryBush   = assembly.GetType("Pathoschild.Stardew.Automate.Framework.Machines.TerrainFeatures.BushMachine");

                    harmony.Patch(
                        original: AccessTools.Method(tapper, "GetOutput"),
                        prefix: new HarmonyMethod(typeof(Patcher), nameof(PatchTapperMachineOutput))
                        );

                    harmony.Patch(
                        original: AccessTools.Method(mushroomBox, "GetOutput"),
                        prefix: new HarmonyMethod(typeof(Patcher), nameof(PatchMushroomBoxMachineOutput))
                        );

                    harmony.Patch(
                        original: AccessTools.Method(berryBush, "GetOutput"),
                        postfix: new HarmonyMethod(typeof(Patcher), nameof(PatchPostBushMachineXP))
                        );
                }
                catch (Exception e)
                {
                    mod.ErrorLog($"Error while trying to patch Automate. Please report this to the mod page of {mod.ModManifest.Name}, not Automate:", e);
                }
            }

            if (mod.Helper.ModRegistry.IsLoaded("BitwiseJonMods.OneClickShedReloader"))
            {
                try
                {
                    mod.DebugLog("This mod patches OneClickShedReloader. If you notice issues with OneClickShedReloader, make sure it happens without this mod before reporting it to the OneClickShedReloader page.");

                    // this is so ugly but I can't include a reference
                    Assembly assembly = null;

                    foreach (var item in AppDomain.CurrentDomain.GetAssemblies())
                    {
                        if (item.GetName().Name.Trim() == "BitwiseJonMods.OneClickShedReloader")
                        {
                            assembly = item;
                            break;
                        }
                    }

                    if (assembly == null)
                    {
                        mod.ErrorLog($"Error while trying to patch OneClickShedReloader. Please report this to the mod page of {mod.ModManifest.Name}, not OneClickShedReloader.");
                        return;
                    }

                    var handler = assembly.GetType("BitwiseJonMods.BuildingContentsHandler");
                    var entry   = assembly.GetType("BitwiseJonMods.ModEntry");

                    harmony.Patch(
                        original: AccessTools.Method(handler, "TryAddItemToPlayerInventory"),
                        prefix: new HarmonyMethod(typeof(Patcher), nameof(TryAddItemToPlayerInventory_Pre))
                        );

                    harmony.Patch(
                        original: AccessTools.Method(handler, "TryAddItemToPlayerInventory"),
                        postfix: new HarmonyMethod(typeof(Patcher), nameof(TryAddItemToPlayerInventory_Post))
                        );

                    harmony.Patch(
                        original: AccessTools.Method(entry, "HarvestAllItemsInBuilding"),
                        postfix: new HarmonyMethod(typeof(Patcher), nameof(ReduceQualityAfterHarvest))
                        );
                }
                catch (Exception e)
                {
                    mod.ErrorLog($"Error while trying to patch OneClickShedReloader. Please report this to the mod page of {mod.ModManifest.Name}, not OneClickShedReloader:", e);
                }
            }
        }
Пример #30
0
 public static bool AreGrapeJsonModsInstalled(ForageFantasy mod)
 {
     return(mod.Helper.ModRegistry.IsLoaded("spacechase0.JsonAssets") && mod.Helper.ModRegistry.IsLoaded("Goldenrevolver.TheGrapeDivide"));
 }