├── .gitattributes
├── FishingAssistant
├── Image
│ └── FishingAssistant.gif
├── manifest.json
├── packages.config
├── I18n.tt
├── FishingAssistant.sln
├── Framework
│ ├── KeyHelper.cs
│ ├── SFishingRod.cs
│ ├── SBobberBar.cs
│ └── SModEntry.cs
├── Menu
│ ├── Option
│ │ ├── DescriptionElement.cs
│ │ ├── BaseOptionElement.cs
│ │ ├── CheckboxOptionElement.cs
│ │ ├── ButtonOptionElement.cs
│ │ ├── KeyListenerOptionElement.cs
│ │ ├── PagingOptionElement.cs
│ │ └── SliderOptionElement.cs
│ ├── MenuHelper.cs
│ └── FishingAssistantMenu.cs
├── Properties
│ └── AssemblyInfo.cs
├── i18n
│ ├── ru.json
│ ├── pt.json
│ ├── de.json
│ ├── zh.json
│ └── default.json
├── Component
│ ├── CheatAction.cs
│ ├── FishPreview.cs
│ └── AutoAction.cs
├── FishingAssistant.csproj
├── ModConfig.cs
├── ModEntry.cs
├── README.md
└── I18n.cs
├── README.md
└── .gitignore
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/FishingAssistant/Image/FishingAssistant.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KilZenc/Stardew-SMAPI-Mods/HEAD/FishingAssistant/Image/FishingAssistant.gif
--------------------------------------------------------------------------------
/FishingAssistant/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "Name": "Fishing Assistant",
3 | "Author": "KilZenc",
4 | "Version": "1.3.5",
5 | "Description": "Personal Fishing Assistant For You",
6 | "UniqueID": "KilZenc.FishingAssistant",
7 | "EntryDll": "FishingAssistant.dll",
8 | "MinimumApiVersion": "3.2.2",
9 | "UpdateKeys": [ "Nexus:5815" ]
10 | }
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # KilZenc Stardew Vally Mod Project
2 | SMAPI mods for stardew valley game.
3 |
4 | ## Fishing Assistant
5 | Your personal fishing assistant. that will handle the tough, boring and tiring fishing for you.
6 |
7 | for more information see [here](FishingAssistant/README.md)
8 |
9 | 
10 |
--------------------------------------------------------------------------------
/FishingAssistant/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/FishingAssistant/I18n.tt:
--------------------------------------------------------------------------------
1 | <#@ template hostspecific="true" language="C#" #>
2 | <#@ output extension=".cs" #>
3 | <#@ assembly name="$(TargetDir)\Pathoschild.Stardew.ModTranslationClassBuilder.dll"#>
4 | <#@ import namespace="Pathoschild.Stardew.ModTranslationClassBuilder" #>
5 | <#=
6 | TranslationClassBuilder.Generate(
7 | jsonPath: this.Host.ResolvePath("i18n/default.json")
8 | )
9 | #>
10 |
--------------------------------------------------------------------------------
/FishingAssistant/FishingAssistant.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30907.101
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FishingAssistant", "FishingAssistant.csproj", "{BE962F18-EE51-4BE9-8DB7-9B1BB5AF94A6}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {BE962F18-EE51-4BE9-8DB7-9B1BB5AF94A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {BE962F18-EE51-4BE9-8DB7-9B1BB5AF94A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {BE962F18-EE51-4BE9-8DB7-9B1BB5AF94A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {BE962F18-EE51-4BE9-8DB7-9B1BB5AF94A6}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {02A4551B-DA51-4AFD-9ABC-F9CF221D161D}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/FishingAssistant/Framework/KeyHelper.cs:
--------------------------------------------------------------------------------
1 | namespace FishingAssistant.Framework
2 | {
3 | internal static class KeyHelper
4 | {
5 | public static string bobberBarHeight = "bobberBarHeight";
6 | public static string bobberBarPos = "bobberBarPos";
7 | public static string bobberPosition = "bobberPosition";
8 | public static string bossFish = "bossFish";
9 | public static string caughtDoubleFish = "caughtDoubleFish";
10 | public static string difficulty = "difficulty";
11 | public static string distanceFromCatching = "distanceFromCatching";
12 | public static string fadeOut = "fadeOut";
13 | public static string fishQuality = "fishQuality";
14 | public static string fishSize = "fishSize";
15 | public static string fromFishPond = "fromFishPond";
16 | public static string perfect = "perfect";
17 | public static string itemCategory = "itemCategory";
18 | public static string treasure = "treasure";
19 | public static string treasureCatchLevel = "treasureCatchLevel";
20 | public static string treasureCaught = "treasureCaught";
21 | public static string treasurePosition = "treasurePosition";
22 | public static string treasureShake = "treasureShake";
23 | public static string whichFish = "whichFish";
24 | }
25 | }
--------------------------------------------------------------------------------
/FishingAssistant/Menu/Option/DescriptionElement.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework;
2 | using Microsoft.Xna.Framework.Graphics;
3 | using StardewValley;
4 | using StardewValley.Menus;
5 |
6 | namespace FishingAssistant.Menu.Option
7 | {
8 | /// An options element which contains descriptive text.
9 | internal class DescriptionElement : BaseOptionsElement
10 | {
11 | /*********
12 | ** Public methods
13 | *********/
14 |
15 | /// Construct an instance.
16 | /// The checkbox label.
17 | public DescriptionElement(string label)
18 | : base(label, -1, -1, 0, 0, 0) { }
19 |
20 | /// Draw the component to the screen.
21 | /// The sprite batch being drawn.
22 | /// The X position at which to draw, relative to the bounds.
23 | /// The Y position at which to draw, relative to the bounds.
24 | /// The menu drawing the component.
25 | public override void draw(SpriteBatch spriteBatch, int slotX, int slotY, IClickableMenu context = null)
26 | {
27 | int yOffset = 0;
28 | spriteBatch.DrawString(Game1.smallFont, this.label, new Vector2(slotX + this.bounds.X, slotY + this.bounds.Y + yOffset), Color.Black);
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/FishingAssistant/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("FishingAssistant")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("FishingAssistant")]
12 | [assembly: AssemblyCopyright("Copyright © 2021")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("be962f18-ee51-4be9-8db7-9b1bb5af94a6")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
--------------------------------------------------------------------------------
/FishingAssistant/Menu/Option/BaseOptionElement.cs:
--------------------------------------------------------------------------------
1 | using StardewModdingAPI;
2 | using StardewValley.Menus;
3 |
4 | namespace FishingAssistant.Menu.Option
5 | {
6 | /// The base implementation for a cheat option element.
7 | internal abstract class BaseOptionsElement : OptionsElement
8 | {
9 | /*********
10 | ** Protected methods
11 | *********/
12 |
13 | /// Construct an instance.
14 | /// The element label.
15 | protected BaseOptionsElement(string label)
16 | : base(label) { }
17 |
18 | /// Construct an instance.
19 | /// The display label.
20 | /// The X pixel position at which to draw the element.
21 | /// The Y pixel position at which to draw the element.
22 | /// The pixel width.
23 | /// The pixel height.
24 | /// The option ID.
25 | protected BaseOptionsElement(string label, int x, int y, int width, int height, int whichOption = -1)
26 | : base(label, x, y, width, height, whichOption) { }
27 |
28 | /// Get the X offset at which to render the element.
29 | protected int GetOffsetX()
30 | {
31 | // Android port doesn't consider the element width, so we do so here
32 | return Constants.TargetPlatform == GamePlatform.Android
33 | ? bounds.Width + 8
34 | : 0;
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/FishingAssistant/i18n/ru.json:
--------------------------------------------------------------------------------
1 | {
2 | //General
3 | "mod.name" : "Fishing Assistant",
4 | "mod.status.enable" : "Включен",
5 | "mod.status.disable" : "Отключен",
6 |
7 | //HUD messages
8 | "hud.message.mod.toggle" : "{0} Fishing Assistant.",
9 | "hud.message.cast.power" : "{0} Макс. сила броска.",
10 | "hud.message.catch.treasure" : "{0} Ловли сундука.",
11 | "hud.message.request.disable" : "Мод будет отключен, когда завершится задание.",
12 | "hud.message.force.enable" : "Нажмите снова {0} для принудительного включения.",
13 | "hud.message.low.stamina" : "Мало энергии.",
14 | "hud.message.inventory.full" : "Полный багаж.",
15 | "hud.message.auto.disable" : "{0} - автоматически отключить мод",
16 | "hud.message.config.saved" : "Новые настройки сохранены",
17 |
18 | //Config Menu
19 | "menu.config.header.control": "Управление",
20 | "menu.config.button.toggle.mod": "Сменить кнопку запуска мода",
21 | "menu.config.button.max.cast.power": "Кнопка макс. броска",
22 | "menu.config.button.catch.treasure": "Кнопка ловли сундуков",
23 | "menu.config.button.open.menu": "Кнопка открытия меню",
24 | "menu.config.reset.control": "Сбросить настройки",
25 | "menu.config.press-new-key": "Нажмите на новую клавишу...",
26 |
27 | "menu.config.header.general": "Общее",
28 | "menu.config.label.mod.status.position": "Расположение статуса мода",
29 | "menu.config.label.auto.pause.fishing": "Включить авто-паузу во время рыбалки",
30 | "menu.config.label.pause.fishing.time": "Пауза во время рыбалки",
31 |
32 | "menu.config.header.fishing.rod": "Рыбная удочка",
33 | "menu.config.label.infinite.bait": "Бесконечная наживка",
34 | "menu.config.label.infinite.tackle": "Бесконечные снасти",
35 |
36 | "menu.config.header.mini-game": "Мини-игра рыбалки",
37 | "menu.config.label.always.perfect": "Всегда безупречно",
38 | "menu.config.label.always.catch.double": "Всегда ловить по две рыбы",
39 | "menu.config.label.always.treasure": "Всегда находить сундук",
40 | "menu.config.label.instant.fishbite": "Мгновенный клев рыбы",
41 | "menu.config.label.instant.catch.fish": "Мгновенная ловля рыбы",
42 | "menu.config.label.instant.catch.treasure": "Мгновенная ловля сундука",
43 | "menu.config.label.fish.difficulty.multiplier": "Множитель сложности рыбы",
44 | "menu.config.label.fish.difficulty.additive": "Добавка к сложности рыбы",
45 | "menu.config.description.fish.difficulty": "Значение, отличимое от этого, можно изменить в config.json.",
46 | "menu.config.description.android-config-note": "Вы можете изменить кнопки на экране в config.json для модов Fishing Assistant и Virtual Keyboard.",
47 |
48 | "menu.config.header.fish.info": "Информация о Рыбалке",
49 | "menu.config.label.fishinfo.display.position": "Расположение информации об рыбе",
50 | "menu.config.label.show.fish.name": "Показывать название рыбы",
51 | "menu.config.label.show.treasure": "Показывать сундук",
52 | "menu.config.label.show.uncaught.fish": "Показывать непойманную рыбу",
53 | "menu.config.label.show.legendaly.fish": "Показывать легендарную рыбу",
54 | }
55 |
--------------------------------------------------------------------------------
/FishingAssistant/Menu/Option/CheckboxOptionElement.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework;
2 | using Microsoft.Xna.Framework.Graphics;
3 | using StardewValley;
4 | using StardewValley.Menus;
5 | using System;
6 |
7 | namespace FishingAssistant.Menu.Option
8 | {
9 | /// A checkbox UI option.
10 | internal class CheckboxOptionElement : BaseOptionsElement
11 | {
12 | /*********
13 | ** Fields
14 | *********/
15 |
16 | /// A callback to invoke when the value changes.
17 | private readonly Action SetValue;
18 |
19 | /// Whether the slider should be disabled.
20 | private readonly Func IsDisabled;
21 |
22 | /*********
23 | ** Accessors
24 | *********/
25 |
26 | /// Whether the checkbox is currently checked.
27 | public bool IsChecked { get; private set; }
28 |
29 | /*********
30 | ** Public methods
31 | *********/
32 |
33 | /// Construct an instance.
34 | /// The checkbox label.
35 | /// The initial value to set.
36 | /// A callback to invoke when the value changes.
37 | public CheckboxOptionElement(string label, bool value, Action setValue, Func disabled = null)
38 | : base(label, -1, -1, 9 * Game1.pixelZoom, 9 * Game1.pixelZoom, 0)
39 | {
40 | this.IsChecked = value;
41 | this.SetValue = setValue;
42 | this.IsDisabled = disabled ?? (() => false);
43 | }
44 |
45 | /// Handle the player clicking the left mouse button.
46 | /// The cursor's X pixel position.
47 | /// The cursor's Y pixel position.
48 | public override void receiveLeftClick(int x, int y)
49 | {
50 | if (greyedOut)
51 | return;
52 | Game1.soundBank.PlayCue("drumkit6");
53 | base.receiveLeftClick(x, y);
54 | IsChecked = !IsChecked;
55 | SetValue(IsChecked);
56 | }
57 |
58 | /// Draw the component to the screen.
59 | /// The sprite batch being drawn.
60 | /// The X position at which to draw, relative to the bounds.
61 | /// The Y position at which to draw, relative to the bounds.
62 | /// The menu drawing the component.
63 | public override void draw(SpriteBatch spriteBatch, int slotX, int slotY, IClickableMenu context = null)
64 | {
65 | this.greyedOut = this.IsDisabled();
66 | spriteBatch.Draw(Game1.mouseCursors, new Vector2(slotX + bounds.X, slotY + bounds.Y), IsChecked ? OptionsCheckbox.sourceRectChecked : OptionsCheckbox.sourceRectUnchecked, Color.White * (greyedOut ? 0.33f : 1f), 0.0f, Vector2.Zero, Game1.pixelZoom, SpriteEffects.None, 0.4f);
67 | base.draw(spriteBatch, slotX + GetOffsetX(), slotY, context);
68 | }
69 | }
70 | }
--------------------------------------------------------------------------------
/FishingAssistant/Menu/Option/ButtonOptionElement.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework;
2 | using Microsoft.Xna.Framework.Graphics;
3 | using StardewValley;
4 | using StardewValley.Menus;
5 | using System;
6 |
7 | namespace FishingAssistant.Menu.Option
8 | {
9 | /// A button which invokes a callback when clicked.
10 | internal class ButtonOptionElement : BaseOptionsElement
11 | {
12 | /*********
13 | ** Fields
14 | *********/
15 |
16 | /// The action to perform when the button is toggled (or null to handle it manually).
17 | private readonly Action Toggle;
18 |
19 | /// The source rectangle for the 'set' button sprite.
20 | private readonly Rectangle SetButtonSprite = new Rectangle(294, 428, 21, 11);
21 |
22 | /// The button area in screen pixels.
23 | private Rectangle SetButtonBounds;
24 |
25 | /*********
26 | ** Public methods
27 | *********/
28 |
29 | /// Construct an instance.
30 | /// The field label.
31 | /// The field width.
32 | /// The action to perform when the button is toggled.
33 | /// Whether the button should be disabled.
34 | public ButtonOptionElement(string label, int slotWidth, Action toggle, bool disabled = false)
35 | : base(label, -1, -1, slotWidth + 1, 11 * Game1.pixelZoom)
36 | {
37 | this.SetButtonBounds = new Rectangle(slotWidth - 28 * Game1.pixelZoom, -1 + Game1.pixelZoom * 3, 21 * Game1.pixelZoom, 11 * Game1.pixelZoom);
38 | this.Toggle = toggle;
39 | this.greyedOut = disabled;
40 | }
41 |
42 | /// Handle the player clicking the left mouse button.
43 | /// The cursor's X pixel position.
44 | /// The cursor's Y pixel position.
45 | public override void receiveLeftClick(int x, int y)
46 | {
47 | if (this.greyedOut || !this.SetButtonBounds.Contains(x, y))
48 | return;
49 |
50 | // callback handler
51 | this.Toggle();
52 | }
53 |
54 | /// Draw the component to the screen.
55 | /// The sprite batch being drawn.
56 | /// The X position at which to draw, relative to the bounds.
57 | /// The Y position at which to draw, relative to the bounds.
58 | /// The menu drawing the component.
59 | public override void draw(SpriteBatch spriteBatch, int slotX, int slotY, IClickableMenu context = null)
60 | {
61 | Utility.drawTextWithShadow(spriteBatch, this.label, Game1.dialogueFont, new Vector2(this.bounds.X + slotX, this.bounds.Y + slotY), this.greyedOut ? Game1.textColor * 0.33f : Game1.textColor, 1f, 0.15f);
62 | Utility.drawWithShadow(spriteBatch, Game1.mouseCursors, new Vector2(this.SetButtonBounds.X + slotX, this.SetButtonBounds.Y + slotY), this.SetButtonSprite, Color.White, 0.0f, Vector2.Zero, Game1.pixelZoom, false, 0.15f);
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/FishingAssistant/i18n/pt.json:
--------------------------------------------------------------------------------
1 | {
2 | //General
3 | "mod.name" : "Fishing Assistant",
4 | "mod.status.enable" : "Ativado",
5 | "mod.status.disable" : "Desativado",
6 | "general.position.left" : "Esquerda",
7 | "general.position.right" : "Direita",
8 | "general.position.top" : "Acima",
9 | "general.position.bottom" : "Abaixo",
10 | "general.position.upper-right" : "Acima, à direita",
11 | "general.position.upper-left" : "Acima, à esquerda",
12 | "general.position.lower-right" : "Abaixo, à direita",
13 | "general.position.lower-left" : "Abaixo, à esquerda",
14 |
15 | //HUD messages
16 | "hud.message.mod.toggle" : "{0} Fishing Assistant - Assistente de Pesca.",
17 | "hud.message.cast.power" : "{0} Barra de distância Máx..",
18 | "hud.message.catch.treasure" : "{0} Pegar tesouro.",
19 | "hud.message.request.disable" : "Mod será desativado após execução atual.",
20 | "hud.message.force.enable" : "Pressione {0} novamente para forçar ativação.",
21 | "hud.message.low.stamina" : "Pouca energia.",
22 | "hud.message.inventory.full" : "Inventário cheio.",
23 | "hud.message.auto.disable" : "Desativar mod automaticamente em {0}",
24 | "hud.message.config.saved" : "Salvar nova configuração",
25 |
26 | //Config Menu
27 | "menu.config.header.control": "Controle",
28 | "menu.config.button.toggle.mod": "Tecla de alternância de mod",
29 | "menu.config.button.max.cast.power": "Tecla de barra de distância",
30 | "menu.config.button.catch.treasure": "Tecla de pegar tesouros",
31 | "menu.config.button.open.menu": "Tecla menu button Abrir botão ",
32 | "menu.config.reset.control": "Resetar",
33 | "menu.config.press-new-key": "Pressione nova tecla...",
34 |
35 | "menu.config.header.general": "Geral",
36 | "menu.config.label.mod.status.position": "Status de posição do mod",
37 | "menu.config.label.auto.pause.fishing": "Ativar pausa automática ao pescar",
38 | "menu.config.label.pause.fishing.time": "Tempo de pausa ao pescar",
39 |
40 | "menu.config.header.fishing.rod": "Vara de pesca",
41 | "menu.config.label.infinite.bait": "Isca infinita",
42 | "menu.config.label.infinite.tackle": "Anzol infinito",
43 |
44 | "menu.config.header.mini-game": "Mini-game de pesca",
45 | "menu.config.label.always.perfect": "Perfeição absoluta",
46 | "menu.config.label.always.catch.double": "Sempre capturar dois peixes",
47 | "menu.config.label.always.treasure": "Sempre encontrar Tesouros",
48 | "menu.config.label.instant.fishbite": "Mordida instantânea de peixe",
49 | "menu.config.label.instant.catch.fish": "Captura instantânea de peixe",
50 | "menu.config.label.instant.catch.treasure": "Captura instantânea de tesouro",
51 | "menu.config.label.fish.difficulty.multiplier": "Multiplicador de dificuldade de peixe",
52 | "menu.config.label.fish.difficulty.additive": "Adicional de Dificuldade de Peixes",
53 | "menu.config.description.fish.difficulty": "Outros valores fora esses que podem ser selecionados nos arquivos externos de configurações.",
54 | "menu.config.description.android-config-note": "Você pode mudar as teclas nos arquivos de configuração externos para os mods Fishing Assistant e Virtual Keyboard.",
55 |
56 | "menu.config.header.fish.info": "Informações sobre os peixes",
57 | "menu.config.label.fishinfo.display.position": "Localização dos peixes",
58 | "menu.config.label.show.fish.name": "Mostrar nome dos peixes",
59 | "menu.config.label.show.treasure": "Mostrar tesouros",
60 | "menu.config.label.show.uncaught.fish": "Mostrar peixes não capturados",
61 | "menu.config.label.show.legendaly.fish": "Mostrar peixes lendários",
62 | }
63 |
--------------------------------------------------------------------------------
/FishingAssistant/i18n/de.json:
--------------------------------------------------------------------------------
1 | {
2 | //General
3 | "mod.name" : "Fishing Assistant",
4 | "mod.status.enable" : "Aktiviert",
5 | "mod.status.disable" : "Deaktiviert",
6 | "general.position.left" : "Links",
7 | "general.position.right" : "Rechts",
8 | "general.position.top" : "Oben",
9 | "general.position.bottom" : "Unten",
10 | "general.position.upper-right" : "Oben-Rechts",
11 | "general.position.upper-left" : "Oben-Links",
12 | "general.position.lower-right" : "Unten-Rechts",
13 | "general.position.lower-left" : "Unten-Links",
14 |
15 | //HUD messages
16 | "hud.message.mod.toggle" : "{0} Fishing Assistant.",
17 | "hud.message.cast.power" : "{0} Max. Wurfkraft.",
18 | "hud.message.catch.treasure" : "{0} Schatz sammeln.",
19 | "hud.message.request.disable" : "Mod wird nach dieser Aktion deaktiviert.",
20 | "hud.message.force.enable" : "Drücke {0} erneut, um Aktivierung zu erzwingen.",
21 | "hud.message.low.stamina" : "Geringe Energie.",
22 | "hud.message.inventory.full" : "Inventar voll.",
23 | "hud.message.auto.disable" : "Auto Mod-Abschaltung an {0}",
24 | "hud.message.config.saved" : "Speichere neue Konfiguration",
25 | "hud.message.auto.attach.bait" : "Wurm-Köder autom. anbringen : {0}",
26 | "hud.message.auto.attach.tackle" : "Spezial-Köder autom. anbringen : {0}",
27 |
28 | //Config Menu
29 | "menu.config.header.control": "Steuerung",
30 | "menu.config.button.toggle.mod": "Mod Durchschalten Taste",
31 | "menu.config.button.max.cast.power": "Wurfkraft Taste",
32 | "menu.config.button.catch.treasure": "Schatz sammeln Taste",
33 | "menu.config.button.open.menu": "Menü öffnen Taste",
34 | "menu.config.reset.control": "Zurücksetzen",
35 | "menu.config.press-new-key": "Drücke neue Taste...",
36 |
37 | "menu.config.header.general": "Allgemein",
38 | "menu.config.label.mod.status.position": "Mod-Status Position",
39 | "menu.config.label.auto.pause.fishing": "Auto-Pause beim Fischen aktivieren",
40 | "menu.config.label.pause.fishing.time": "Fangzeit pausieren",
41 |
42 | "menu.config.header.fishing.rod": "Angel",
43 | "menu.config.label.auto.attach.bait": "Wurm-Köder autom. anbringen",
44 | "menu.config.label.auto.attach.tackle": "Spezial-Köder autom. anbringen",
45 | "menu.config.label.infinite.bait": "Unendlich Wurm-Köder",
46 | "menu.config.label.infinite.tackle": "Unendlich Spezial-Köder",
47 |
48 | "menu.config.header.mini-game": "Fischen Mini-Game",
49 | "menu.config.label.always.perfect": "Immer Perfekt",
50 | "menu.config.label.always.catch.double": "Immer doppelten Fisch fangen",
51 | "menu.config.label.always.treasure": "Immer Schatz finden",
52 | "menu.config.label.instant.fishbite": "Sofortiger Anbiss der Fische",
53 | "menu.config.label.instant.catch.fish": "Sofortiges Fangen der Fische",
54 | "menu.config.label.instant.catch.treasure": "Sofortiges Schatz sammeln",
55 | "menu.config.label.fish.difficulty.multiplier": "Fisch-Schwierigkeitsmultiplikator",
56 | "menu.config.label.fish.difficulty.additive": "Fisch-Schwierigkeitszusatz",
57 | "menu.config.description.fish.difficulty": "Ein anderer Wert als dieser kann in der Konfigurationsdatei eingestellt werden.",
58 | "menu.config.description.android-config-note": "Du kannst die On-Screen-Tasten in den Konfigurationsdateien für die Mods Fishing Assistant und Virtual Keyboard ändern.",
59 |
60 | "menu.config.header.fish.info": "Angel-Informationen",
61 | "menu.config.label.fishinfo.display.position": "Fischinfo Position",
62 | "menu.config.label.show.fish.name": "Zeige Fischnamen",
63 | "menu.config.label.show.treasure": "Zeige Schatz",
64 | "menu.config.label.show.uncaught.fish": "Zeige ungefangenen Fisch",
65 | "menu.config.label.show.legendaly.fish": "Zeige legendären Fisch",
66 | }
67 |
--------------------------------------------------------------------------------
/FishingAssistant/i18n/zh.json:
--------------------------------------------------------------------------------
1 | {
2 | //General
3 | "mod.name" : "钓鱼助手",
4 | "mod.status.enable" : "启用",
5 | "mod.status.disable" : "禁用",
6 | "general.position.left" : "左侧",
7 | "general.position.right" : "右侧",
8 | "general.position.top" : "顶部",
9 | "general.position.bottom" : "底部",
10 | "general.position.upper-right" : "右上角",
11 | "general.position.upper-left" : "左上角",
12 | "general.position.lower-right" : "右下角",
13 | "general.position.lower-left" : "左下角",
14 |
15 | //HUD messages
16 | "hud.message.mod.toggle" : "{0} 钓鱼助手。",
17 | "hud.message.cast.power" : "{0} 最大抛竿力量。",
18 | "hud.message.catch.treasure" : "{0} 捕获宝藏。",
19 | "hud.message.request.disable" : "模组将在任务完成后禁用。",
20 | "hud.message.force.enable" : "再次按下 {0} 以强制启用。",
21 | "hud.message.low.stamina" : "低能量。",
22 | "hud.message.inventory.full" : "物品栏已满。",
23 | "hud.message.auto.disable" : "在 {0} 自动禁用模组",
24 | "hud.message.config.saved" : "正在保存新配置",
25 | "hud.message.auto.attach.bait" : "自动安装鱼饵:{0}",
26 | "hud.message.auto.attach.tackle" : "自动安装钓具:{0}",
27 |
28 | //Config Menu
29 | "menu.config.header.control": "控制",
30 | "menu.config.button.toggle.mod": "开关模组按钮",
31 | "menu.config.button.max.cast.power": "抛竿力量按钮",
32 | "menu.config.button.catch.treasure": "捕获宝藏按钮",
33 | "menu.config.button.open.menu": "打开菜单按钮",
34 | "menu.config.reset.control": "重置",
35 | "menu.config.press-new-key": "按下新按键…",
36 |
37 | "menu.config.header.general": "常规",
38 | "menu.config.label.mod.status.position": "模组状态位置",
39 | "menu.config.label.auto.pause.fishing": "自动暂停钓鱼",
40 | "menu.config.label.pause.fishing.time": "暂停钓鱼时间",
41 | "menu.config.label.auto.eat.food": "自动吃食物",
42 | "menu.config.label.energy.to.eat.food": "吃的能量",
43 | "menu.config.label.allow.eat.fish": "允许吃鱼",
44 | "menu.config.etc.allow.eat.fish.warning": "小心,传说之鱼可能会被吃掉。",
45 | "menu.config.etc.when-low-energy": "低能量时",
46 |
47 | "menu.config.header.automation": "自动化",
48 | "menu.config.label.current.preset": "自动化预设",
49 | "menu.config.label.preset.default": "默认",
50 | "menu.config.label.preset.custom": "自定义",
51 | "menu.config.label.preset.disable": "禁用",
52 | "menu.config.label.automation.auto.cast": "自动抛竿",
53 | "menu.config.label.automation.auto.hook": "自动上钩",
54 | "menu.config.label.automation.auto.play-mini-game": "自动玩迷你游戏",
55 | "menu.config.label.automation.auto.close-popup": "自动关闭弹窗",
56 | "menu.config.label.automation.auto.loot-treasure": "自动收集宝藏",
57 | "menu.config.description.enable.custom.automation": "启用此部分,将“自动化预设”设置为“自定义”。",
58 |
59 | "menu.config.header.fishing.rod": "鱼竿",
60 | "menu.config.label.auto.attach.bait": "自动安装鱼饵",
61 | "menu.config.label.auto.attach.tackle": "自动安装钓具",
62 | "menu.config.label.infinite.bait": "无限鱼饵",
63 | "menu.config.label.infinite.tackle": "无限钓具",
64 |
65 | "menu.config.header.enchantment": "附魔",
66 | "menu.config.label.enchantment.auto-hook": "添加自动上钩附魔",
67 | "menu.config.label.enchantment.efficient": "添加省力附魔",
68 | "menu.config.label.enchantment.master": "添加精通附魔",
69 | "menu.config.label.enchantment.preserving": "添加耐用附魔",
70 | "menu.config.label.enchantment.when-held": "仅在持有时添加附魔",
71 |
72 | "menu.config.header.mini-game": "迷你钓鱼游戏",
73 | "menu.config.label.always.perfect": "总是完美",
74 | "menu.config.label.always.catch.double": "总是钓到两条鱼",
75 | "menu.config.label.always.treasure": "总是找到宝藏",
76 | "menu.config.label.instant.fishbite": "立即咬钩",
77 | "menu.config.label.instant.catch.fish": "立即捕获鱼",
78 | "menu.config.label.instant.catch.treasure": "立即捕获宝藏",
79 | "menu.config.label.fish.difficulty.multiplier": "鱼类难度系数",
80 | "menu.config.label.fish.difficulty.additive": "鱼类难度附加值",
81 | "menu.config.description.fish.difficulty": "可以在配置文件中设置其他值。",
82 | "menu.config.description.android-config-note": "你可以在钓鱼助手和虚拟键盘(Virtual Keyboard)模组的配置文件中更改屏幕上的按钮。",
83 |
84 | "menu.config.header.fish.info": "鱼类信息",
85 | "menu.config.label.fishinfo.display.position": "鱼类信息位置",
86 | "menu.config.label.show.fish.name": "显示鱼的名称",
87 | "menu.config.label.show.treasure": "显示宝藏",
88 | "menu.config.label.show.uncaught.fish": "显示未捕获的鱼",
89 | "menu.config.label.show.legendaly.fish": "显示传说鱼类",
90 | }
91 |
--------------------------------------------------------------------------------
/FishingAssistant/Menu/MenuHelper.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework;
2 | using Microsoft.Xna.Framework.Graphics;
3 | using StardewValley;
4 | using StardewValley.Menus;
5 |
6 | namespace FishingAssistant.Menu
7 | {
8 | internal static class MenuHelper
9 | {
10 | public static string GetLocalizationText(string value)
11 | {
12 | switch (value)
13 | {
14 | case "Left": return I18n.General_Position_Left();
15 | case "Right": return I18n.General_Position_Right();
16 | case "Top": return I18n.General_Position_Top();
17 | case "Bottom": return I18n.General_Position_Bottom();
18 | case "UpperRight": return I18n.General_Position_UpperRight();
19 | case "UpperLeft": return I18n.General_Position_UpperLeft();
20 | case "LowerRight": return I18n.General_Position_LowerRight();
21 | case "LowerLeft": return I18n.General_Position_LowerLeft();
22 | case "Default": return I18n.Menu_Config_Label_Preset_Default();
23 | case "Custom": return I18n.Menu_Config_Label_Preset_Custom();
24 | case "Disable": return I18n.Menu_Config_Label_Preset_Disable();
25 | default: return "";
26 | }
27 | }
28 |
29 | /// Draw a button texture fir the given text to the screen.
30 | /// The X position at which to draw.
31 | /// The Y position at which to draw.
32 | /// The text font.
33 | /// The button text.
34 | /// The button's horizontal alignment relative to . The possible values are 0 (left), 1 (center), or 2 (right).
35 | /// The button opacity, as a value from 0 (transparent) to 1 (opaque).
36 | /// Whether to draw a shadow under the tab.
37 | public static void DrawTab(int x, int y, SpriteFont font, string text, int align = 0, float alpha = 1, bool drawShadow = true)
38 | {
39 | SpriteBatch spriteBatch = Game1.spriteBatch;
40 | Vector2 bounds = font.MeasureString(text);
41 |
42 | DrawTab(x, y, (int)bounds.X, (int)bounds.Y, out Vector2 drawPos, align, alpha, drawShadow: drawShadow);
43 | Utility.drawTextWithShadow(spriteBatch, text, font, drawPos, Game1.textColor);
44 | }
45 |
46 | /// Draw a button texture to the screen.
47 | /// The X position at which to draw.
48 | /// The Y position at which to draw.
49 | /// The width of the button's inner content.
50 | /// The height of the button's inner content.
51 | /// The position at which the content should be drawn.
52 | /// The button's horizontal alignment relative to . The possible values are 0 (left), 1 (center), or 2 (right).
53 | /// The button opacity, as a value from 0 (transparent) to 1 (opaque).
54 | /// Whether to draw a shadow under the tab.
55 | public static void DrawTab(int x, int y, int innerWidth, int innerHeight, out Vector2 innerDrawPosition, int align = 0, float alpha = 1, bool drawShadow = true)
56 | {
57 | SpriteBatch spriteBatch = Game1.spriteBatch;
58 |
59 | // calculate outer coordinates
60 | int outerWidth = innerWidth + 4 * Game1.pixelZoom * 2;
61 | int outerHeight = innerHeight + Game1.tileSize / 3;
62 | switch (align)
63 | {
64 | case 1: align = -outerWidth / 2; break;
65 | case 2: align = -outerWidth; break;
66 | default: align = 0; break;
67 | }
68 | int offsetX = align;
69 |
70 | // draw texture
71 | IClickableMenu.drawTextureBox(spriteBatch, Game1.menuTexture, new Rectangle(0, 256, 60, 60), x + offsetX, y, outerWidth, outerHeight + Game1.tileSize / 16, Color.White * alpha, drawShadow: drawShadow);
72 | innerDrawPosition = new Vector2(x + 4 * Game1.pixelZoom + offsetX, y + 4 * Game1.pixelZoom);
73 | }
74 | }
75 | }
--------------------------------------------------------------------------------
/FishingAssistant/Component/CheatAction.cs:
--------------------------------------------------------------------------------
1 | using StardewModdingAPI;
2 | using StardewValley;
3 |
4 | namespace FishingAssistant
5 | {
6 | internal partial class ModEntry : Mod
7 | {
8 | private void AddEnchantment()
9 | {
10 | if (Config.AddAutoHookEnchantment && !fishingRod.hasEnchantmentOfType())
11 | fishingRod.enchantments.Add(new AutoHookEnchantment());
12 |
13 | if (Config.AddEfficientEnchantment && !fishingRod.hasEnchantmentOfType())
14 | fishingRod.enchantments.Add(new EfficientToolEnchantment());
15 |
16 | if (Config.AddMasterEnchantment && !fishingRod.hasEnchantmentOfType())
17 | fishingRod.enchantments.Add(new MasterEnchantment());
18 |
19 | if (Config.AddPreservingEnchantment && !fishingRod.hasEnchantmentOfType())
20 | fishingRod.enchantments.Add(new PreservingEnchantment());
21 | }
22 |
23 | /// Make bait and tackle last long forever
24 | private void ApplyInfiniteBaitAndTackle()
25 | {
26 | if (!(Context.IsWorldReady && fishingRod != null))
27 | return;
28 |
29 | if (Config.InfiniteBait && fishingRod.attachments?.Length > 0 && fishingRod.attachments[0] != null && fishingRod.attachments[0].Stack < fishingRod.attachments[0].maximumStackSize())
30 | fishingRod.attachments[0].Stack = fishingRod.attachments[0].maximumStackSize();
31 |
32 | if (Config.InfiniteTackle && fishingRod.attachments?.Length > 1 && fishingRod.attachments[1] != null && fishingRod.attachments[1].uses.Value != 0)
33 | fishingRod.attachments[1].uses.Value = 0;
34 | }
35 |
36 | /// Make fish instantly bite when fishing
37 | private void InstantFishBite()
38 | {
39 | if (Config.InstantFishBite && (IsRodFishing && !IsRodHit && RodTimeUntilFishBite > 0))
40 | RodTimeUntilFishBite = 0;
41 | }
42 |
43 | /// End fishing minigame
44 | private void EndMiniGame()
45 | {
46 | if (Game1.isFestival())
47 | return;
48 |
49 | Game1.playSound("jingle1");
50 |
51 | int attachmentValue = fishingRod.attachments[0] == null ? -1 : fishingRod.attachments[0].parentSheetIndex;
52 | bool caughtDouble = Config.AlwaysCatchDoubleFish || (!BarBossFish && attachmentValue == 774 && Game1.random.NextDouble() < 0.25 + Game1.player.DailyLuck / 2.0);
53 |
54 | fishingRod.pullFishFromWater(BarWhichFish, BarFishSize, BarFishQuality, (int)BarDifficulty, BarTreasureCaught, BarPerfect, BarFromFishPond, caughtDouble);
55 | Game1.exitActiveMenu();
56 |
57 | Game1.setRichPresence("location", Game1.currentLocation.Name);
58 | }
59 |
60 | /// Force treasure spawn every time when fishing
61 | private void AlwayFindTreasure()
62 | {
63 | if (Config.AlwaysFindTreasure && !Game1.isFestival())
64 | BarHasTreasure = true;
65 | }
66 |
67 | /// Make fish instantly catch, simply skip minigame
68 | private void InstantCatchFish()
69 | {
70 | if (Config.InstantCatchFish)
71 | {
72 | if (BarHasTreasure)
73 | BarTreasureCaught = true;
74 | BarDistanceFromCatching = 1.0f;
75 | }
76 | }
77 |
78 | /// Make treasure is instantly caught when appearing
79 | private void InstantCatchTreasure()
80 | {
81 | if (Config.InstantCatchTreasure && (BarHasTreasure || Config.AlwaysFindTreasure))
82 | BarTreasureCaught = true;
83 | }
84 |
85 | /// Override fish difficult
86 | private void OverrideFishDifficult()
87 | {
88 | BarDifficulty *= Config.FishDifficultyMultiplier;
89 | BarDifficulty += Config.FishDifficultyAdditive;
90 | if (BarDifficulty < 0) BarDifficulty = 0;
91 | }
92 |
93 | /// Force fishing minigame alway perfect
94 | private void AlwayPerfectResult()
95 | {
96 | if (Config.AlwaysPerfect)
97 | BarPerfect = true;
98 | }
99 |
100 | /// Force fishing rod cast power to max
101 | private void MaxCastPower()
102 | {
103 | if (maxCastPower)
104 | RodCastPower = 1.01f;
105 | }
106 | }
107 | }
--------------------------------------------------------------------------------
/FishingAssistant/i18n/default.json:
--------------------------------------------------------------------------------
1 | {
2 | //General
3 | "mod.name" : "Fishing Assistant",
4 | "mod.status.enable" : "Enable",
5 | "mod.status.disable" : "Disable",
6 | "general.position.left" : "Left",
7 | "general.position.right" : "Right",
8 | "general.position.top" : "Top",
9 | "general.position.bottom" : "Bottom",
10 | "general.position.upper-right" : "UpperRight",
11 | "general.position.upper-left" : "UpperLeft",
12 | "general.position.lower-right" : "LowerRight",
13 | "general.position.lower-left" : "LowerLeft",
14 |
15 | //HUD messages
16 | "hud.message.mod.toggle" : "{0} Fishing Assistant.",
17 | "hud.message.cast.power" : "{0} Max cast power.",
18 | "hud.message.catch.treasure" : "{0} Catch treasure.",
19 | "hud.message.request.disable" : "Mod will disable after task is finished.",
20 | "hud.message.force.enable" : "Pressed {0} again to force enable.",
21 | "hud.message.low.stamina" : "Low energy.",
22 | "hud.message.inventory.full" : "Inventory full.",
23 | "hud.message.auto.disable" : "Auto disable mod on {0}",
24 | "hud.message.config.saved" : "Saving new config",
25 | "hud.message.auto.attach.bait" : "Auto attach bait : {0}",
26 | "hud.message.auto.attach.tackle" : "Auto attach tackle : {0}",
27 |
28 | //Config Menu
29 | "menu.config.header.control": "Control",
30 | "menu.config.button.toggle.mod": "Toggle Mod Button",
31 | "menu.config.button.max.cast.power": "Cast power button",
32 | "menu.config.button.catch.treasure": "Catch treasure button",
33 | "menu.config.button.open.menu": "Open menu button",
34 | "menu.config.reset.control": "Reset",
35 | "menu.config.press-new-key": "Press New Key...",
36 |
37 | "menu.config.header.general": "General",
38 | "menu.config.label.mod.status.position": "Mod status position",
39 | "menu.config.label.auto.pause.fishing": "Auto pause fishing",
40 | "menu.config.label.pause.fishing.time": "Pause fishing time",
41 | "menu.config.label.auto.eat.food": "Auto eat food",
42 | "menu.config.label.energy.to.eat.food": "Energy to eat",
43 | "menu.config.label.allow.eat.fish": "Allow eating fish",
44 | "menu.config.etc.allow.eat.fish.warning": "Be careful, the legendary fish may be eaten.",
45 | "menu.config.etc.when-low-energy": "When low energy",
46 |
47 | "menu.config.header.automation": "Automation",
48 | "menu.config.label.current.preset": "Automation preset",
49 | "menu.config.label.preset.default": "Default",
50 | "menu.config.label.preset.custom": "Custom",
51 | "menu.config.label.preset.disable": "Disable",
52 | "menu.config.label.automation.auto.cast": "Auto cast fishing rod",
53 | "menu.config.label.automation.auto.hook": "Auto hook fish",
54 | "menu.config.label.automation.auto.play-mini-game": "Auto play mini-game",
55 | "menu.config.label.automation.auto.close-popup": "Auto close popup",
56 | "menu.config.label.automation.auto.loot-treasure": "Auto loot treasure",
57 | "menu.config.description.enable.custom.automation": "To enable this section. set Automation preset to Custom.",
58 |
59 | "menu.config.header.fishing.rod": "Fishing rod",
60 | "menu.config.label.auto.attach.bait": "Auto attach bait",
61 | "menu.config.label.auto.attach.tackle": "Auto attach tackle",
62 | "menu.config.label.infinite.bait": "Infinite bait",
63 | "menu.config.label.infinite.tackle": "Infinite tackle",
64 |
65 | "menu.config.header.enchantment": "Enchantment",
66 | "menu.config.label.enchantment.auto-hook": "Add Auto-Hook enchantment",
67 | "menu.config.label.enchantment.efficient": "Add Efficient enchantment",
68 | "menu.config.label.enchantment.master": "Add Master enchantment",
69 | "menu.config.label.enchantment.preserving": "Add Preserving enchantment",
70 | "menu.config.label.enchantment.when-held": "Only add enchantment when held",
71 |
72 | "menu.config.header.mini-game": "Fishing mini-game",
73 | "menu.config.label.always.perfect": "Always Perfect",
74 | "menu.config.label.always.catch.double": "Always catch double fish",
75 | "menu.config.label.always.treasure": "Always found treasure",
76 | "menu.config.label.instant.fishbite": "Instant fish bite",
77 | "menu.config.label.instant.catch.fish": "Instant catch fish",
78 | "menu.config.label.instant.catch.treasure": "Instant catch treasure",
79 | "menu.config.label.fish.difficulty.multiplier": "Fish difficulty multiplier",
80 | "menu.config.label.fish.difficulty.additive": "Fish difficulty additive",
81 | "menu.config.description.fish.difficulty": "Value other than this can be set in config file.",
82 | "menu.config.description.android-config-note": "You can change the on-screen buttons in the config files for the Fishing Assistant and Virtual Keyboard mods.",
83 |
84 | "menu.config.header.fish.info": "Fishing information",
85 | "menu.config.label.fishinfo.display.position": "Fish info position",
86 | "menu.config.label.show.fish.name": "Show fish name",
87 | "menu.config.label.show.treasure": "Show treasure",
88 | "menu.config.label.show.uncaught.fish": "Show uncaught fish",
89 | "menu.config.label.show.legendaly.fish": "Show legendary fish",
90 | }
91 |
--------------------------------------------------------------------------------
/FishingAssistant/Menu/Option/KeyListenerOptionElement.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework;
2 | using Microsoft.Xna.Framework.Graphics;
3 | using Microsoft.Xna.Framework.Input;
4 | using StardewModdingAPI;
5 | using StardewValley;
6 | using StardewValley.Menus;
7 | using System;
8 |
9 | namespace FishingAssistant.Menu.Option
10 | {
11 | /// A button which lets the user choose a key binding.
12 | internal class KeyListenerOptionElement : BaseOptionsElement
13 | {
14 | /*********
15 | ** Fields
16 | *********/
17 |
18 | /// The current key binding.
19 | private SButton Value;
20 |
21 | /// The action to perform when the key binding is chosen.
22 | private readonly Action SetValue;
23 |
24 | /// The translated 'press new key' label.
25 | private readonly string PressNewKeyLabel;
26 |
27 | /// The source rectangle for the 'set' button sprite.
28 | private readonly Rectangle SetButtonSprite = new Rectangle(294, 428, 21, 11);
29 |
30 | /// The button area in screen pixels.
31 | private Rectangle SetButtonBounds;
32 |
33 | /// The button to set when the player clears it.
34 | private readonly SButton ClearToButton;
35 |
36 | private string ListenerMessage;
37 | private bool Listening;
38 |
39 | /*********
40 | ** Public methods
41 | *********/
42 |
43 | /// Construct an instance.
44 | /// The field label.
45 | /// The field width.
46 | /// The current key binding.
47 | /// The action to perform when the button is toggled.
48 | /// The button to set when the player clears it.
49 | public KeyListenerOptionElement(string label, int slotWidth, SButton value, Action setValue, SButton clearToButton = SButton.None)
50 | : base(label, -1, -1, slotWidth + 1, 11 * Game1.pixelZoom)
51 | {
52 | Value = value;
53 | PressNewKeyLabel = I18n.Menu_Config_PressNewKey();
54 | SetValue = setValue;
55 | SetButtonBounds = new Rectangle(slotWidth - 28 * Game1.pixelZoom, -1 + Game1.pixelZoom * 3, 21 * Game1.pixelZoom, 11 * Game1.pixelZoom);
56 | ClearToButton = clearToButton;
57 | }
58 |
59 | /// Handle the player clicking the left mouse button.
60 | /// The cursor's X pixel position.
61 | /// The cursor's Y pixel position.
62 | public override void receiveLeftClick(int x, int y)
63 | {
64 | if (greyedOut || Listening || !SetButtonBounds.Contains(x, y) || Constants.TargetPlatform == GamePlatform.Android)
65 | return;
66 |
67 | Listening = true;
68 | Game1.soundBank.PlayCue("breathin");
69 | GameMenu.forcePreventClose = true;
70 | ListenerMessage = PressNewKeyLabel;
71 | }
72 |
73 | /// Handle the player pressing a keyboard button.
74 | /// The key that was pressed.
75 | public override void receiveKeyPress(Keys key)
76 | {
77 | if (greyedOut || !Listening)
78 | return;
79 |
80 | if (key == Keys.Escape)
81 | {
82 | Value = ClearToButton;
83 | Game1.soundBank.PlayCue("bigDeSelect");
84 | }
85 | else
86 | {
87 | Value = key.ToSButton();
88 | Game1.soundBank.PlayCue("coin");
89 | }
90 |
91 | SetValue(Value);
92 | Listening = false;
93 | GameMenu.forcePreventClose = false;
94 | }
95 |
96 | /// Draw the component to the screen.
97 | /// The sprite batch being drawn.
98 | /// The X position at which to draw, relative to the bounds.
99 | /// The Y position at which to draw, relative to the bounds.
100 | /// The menu drawing the component.
101 | public override void draw(SpriteBatch spriteBatch, int slotX, int slotY, IClickableMenu context = null)
102 | {
103 | Utility.drawTextWithShadow(spriteBatch, $"{label}: {Value}", Game1.dialogueFont, new Vector2(bounds.X + slotX, bounds.Y + slotY), greyedOut ? Game1.textColor * 0.33f : Game1.textColor, 1f, 0.15f);
104 | if (Constants.TargetPlatform != GamePlatform.Android)
105 | Utility.drawWithShadow(spriteBatch, Game1.mouseCursors, new Vector2(SetButtonBounds.X + slotX, SetButtonBounds.Y + slotY), SetButtonSprite, Color.White, 0.0f, Vector2.Zero, Game1.pixelZoom, false, 0.15f);
106 |
107 | if (Listening)
108 | {
109 | spriteBatch.Draw(Game1.staminaRect, new Rectangle(0, 0, Game1.graphics.GraphicsDevice.Viewport.Width, Game1.graphics.GraphicsDevice.Viewport.Height), new Rectangle(0, 0, 1, 1), Color.Black * 0.75f, 0.0f, Vector2.Zero, SpriteEffects.None, 0.999f);
110 | spriteBatch.DrawString(Game1.dialogueFont, ListenerMessage, Utility.getTopLeftPositionForCenteringOnScreen(Game1.tileSize * 3, Game1.tileSize), Color.White, 0.0f, Vector2.Zero, 1f, SpriteEffects.None, 0.9999f);
111 | }
112 | }
113 | }
114 | }
--------------------------------------------------------------------------------
/FishingAssistant/Menu/Option/PagingOptionElement.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework;
2 | using Microsoft.Xna.Framework.Graphics;
3 | using Microsoft.Xna.Framework.Input;
4 | using StardewValley;
5 | using StardewValley.Menus;
6 | using System;
7 | using System.Collections.Generic;
8 |
9 | namespace FishingAssistant.Menu.Option
10 | {
11 | //Still not available to use
12 | internal class PagingOptionElement : BaseOptionsElement
13 | {
14 | private readonly List options = new List();
15 |
16 | private readonly List displayOptions = new List();
17 |
18 | private readonly Action SetValue;
19 |
20 | private int selected;
21 |
22 | private static bool snapNext;
23 |
24 | private static bool snapPrevious;
25 |
26 | private Rectangle previousButton;
27 |
28 | private Rectangle nextButton;
29 |
30 | private static Rectangle previousButtonSource = new Rectangle(352, 495, 12, 11);
31 |
32 | private static Rectangle nextButtonSource = new Rectangle(365, 495, 12, 11);
33 |
34 | private Rectangle displayTxt;
35 |
36 | public PagingOptionElement(string label, List options, Action setValue, int x = -1, int y = -1)
37 | : base(label, x, y, 7 * Game1.pixelZoom, 7 * Game1.pixelZoom)
38 | {
39 | base.label = label;
40 | this.options = options;
41 | this.displayOptions = options;
42 | this.SetValue = setValue;
43 |
44 | if (x == -1) { x = 32; }
45 | if (y == -1) { y = 16; }
46 |
47 | int margin = 14;
48 | int width = 48;
49 | int hight = 44;
50 |
51 | int txtSize = (int)Game1.dialogueFont.MeasureString(options[0]).X;
52 | foreach (string displayOption in displayOptions)
53 | {
54 | txtSize = Math.Max((int)Game1.dialogueFont.MeasureString(displayOption).X, txtSize);
55 | }
56 |
57 | base.bounds = new Rectangle(x, y, txtSize + (width * 2) + (margin * 2), hight);
58 | this.previousButton = new Rectangle(x, y, width, hight);
59 | this.displayTxt = new Rectangle(x + previousButton.Width + margin, y, txtSize, hight);
60 | this.nextButton = new Rectangle(x + previousButton.Width + (margin * 2) + txtSize, y, width, hight);
61 | }
62 |
63 | public override void receiveLeftClick(int x, int y)
64 | {
65 | if (!base.greyedOut && this.options.Count > 0)
66 | {
67 | if (this.previousButton.Contains(x, y) && this.selected != 0)
68 | {
69 | this.selected--;
70 | snapPrevious = true;
71 | Game1.playSound("drumkit6");
72 | }
73 | else if (this.nextButton.Contains(x, y) && this.selected != this.options.Count - 1)
74 | {
75 | this.selected++;
76 | snapNext = true;
77 | Game1.playSound("drumkit6");
78 | }
79 |
80 | if (this.selected < 0)
81 | this.selected = 0;
82 | else if (this.selected >= this.options.Count)
83 | this.selected = this.options.Count - 1;
84 |
85 | SetValue(options[selected]);
86 | }
87 | }
88 |
89 | public override void receiveKeyPress(Keys key)
90 | {
91 | base.receiveKeyPress(key);
92 | if (Game1.options.snappyMenus && Game1.options.gamepadControls)
93 | {
94 | if (Game1.options.doesInputListContain(Game1.options.moveRightButton, key))
95 | {
96 | this.receiveLeftClick(this.nextButton.Center.X, this.nextButton.Center.Y);
97 | }
98 | else if (Game1.options.doesInputListContain(Game1.options.moveLeftButton, key))
99 | {
100 | this.receiveLeftClick(this.previousButton.Center.X, this.previousButton.Center.Y);
101 | }
102 | }
103 | }
104 |
105 | public override void draw(SpriteBatch b, int slotX, int slotY, IClickableMenu context = null)
106 | {
107 | b.Draw(Game1.mouseCursors, new Vector2(slotX + this.previousButton.X, slotY + this.previousButton.Y), previousButtonSource, Color.White * (base.greyedOut ? 0.33f : 1f) * ((this.selected == 0) ? 0.5f : 1f), 0f, Vector2.Zero, 4f, SpriteEffects.None, 0.4f);
108 | b.DrawString(Game1.dialogueFont, (this.selected < this.displayOptions.Count && this.selected != -1) ? this.displayOptions[this.selected] : "", new Vector2(slotX + this.displayTxt.X, slotY + this.displayTxt.Y), Game1.textColor);
109 | b.Draw(Game1.mouseCursors, new Vector2(slotX + this.nextButton.X, slotY + this.nextButton.Y), nextButtonSource, Color.White * (base.greyedOut ? 0.33f : 1f) * ((this.selected == this.displayOptions.Count - 1) ? 0.5f : 1f), 0f, Vector2.Zero, 4f, SpriteEffects.None, 0.4f);
110 |
111 | if (!Game1.options.snappyMenus && Game1.options.gamepadControls)
112 | {
113 | if (snapPrevious)
114 | {
115 | Game1.setMousePosition(slotX + this.previousButton.Center.X, slotY + this.previousButton.Center.Y);
116 | snapPrevious = false;
117 | }
118 | else if (snapNext)
119 | {
120 | Game1.setMousePosition(slotX + this.nextButton.Center.X, slotY + this.nextButton.Center.Y);
121 | snapNext = false;
122 | }
123 | }
124 | Utility.drawTextWithShadow(b, label, Game1.dialogueFont, new Vector2(slotX + nextButton.X + nextButton.Width + 4 + GetOffsetX(), slotY + this.bounds.Y), Game1.textColor);
125 | }
126 | }
127 | }
--------------------------------------------------------------------------------
/FishingAssistant/FishingAssistant.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {BE962F18-EE51-4BE9-8DB7-9B1BB5AF94A6}
8 | Library
9 | Properties
10 | FishingAssistant
11 | FishingAssistant
12 | v4.5.2
13 | 512
14 | true
15 |
16 |
17 |
18 |
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 | packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll
41 |
42 |
43 | packages\Pathoschild.Stardew.ModTranslationClassBuilder.1.0.0\lib\net452\Pathoschild.Stardew.ModTranslationClassBuilder.dll
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | True
60 | True
61 | I18n.tt
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | TextTemplatingFileGenerator
94 | I18n.cs
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/FishingAssistant/ModConfig.cs:
--------------------------------------------------------------------------------
1 | using StardewModdingAPI;
2 |
3 | namespace FishingAssistant
4 | {
5 | internal class ModConfig
6 | {
7 | /// The default values.
8 | public static ModConfig Defaults { get; } = new ModConfig();
9 |
10 | /// Button for toggle max or free fishing rod cast power
11 | public SButton EnableModButton { get; set; } = SButton.F5;
12 |
13 | /// Button for toggle max or free fishing rod cast power
14 | public SButton CastPowerButton { get; set; } = SButton.F6;
15 |
16 | /// Button for toggle catch or ignore treasure in fishing minigame
17 | public SButton CatchTreasureButton { get; set; } = SButton.F7;
18 |
19 | /// Button for roload config file
20 | public SButton OpenMenuButton { get; set; } = SButton.F8;
21 |
22 | /// Whether the game should consider every catch to be perfectly executed, even if it wasn't.
23 | public bool AlwaysPerfect { get; set; } = false;
24 |
25 | /// Whether to always find treasure.
26 | public bool AlwaysFindTreasure { get; set; } = false;
27 |
28 | /// Make fish to bite instantly.
29 | public bool InstantFishBite { get; set; } = false;
30 |
31 | /// Whether to catch fish instantly.
32 | public bool InstantCatchFish { get; set; } = false;
33 |
34 | /// Whether to catch treasure instantly.
35 | public bool InstantCatchTreasure { get; set; } = false;
36 |
37 | /// Whether fishing tackles last forever.
38 | public bool InfiniteTackle { get; set; } = false;
39 |
40 | /// Whether fishing bait lasts forever.
41 | public bool InfiniteBait { get; set; } = false;
42 |
43 | /// A multiplier applied to the fish difficulty. This can a number between 0 and 1 to lower difficulty, or more than 1 to increase it.
44 | public float FishDifficultyMultiplier { get; set; } = 1;
45 |
46 | /// A value added to the fish difficulty. This can be less than 0 to decrease difficulty, or more than 0 to increase it.
47 | public float FishDifficultyAdditive { get; set; } = 0;
48 |
49 | /// Make you catch double fish every time
50 | public bool AlwaysCatchDoubleFish { get; set; } = false;
51 |
52 | /// Position to display fish info when playing fishing minigame
53 | public string ModStatusDisplayPosition { get; set; } = "Right";
54 |
55 | /// Should mod show fish info while catching fish?
56 | public bool DisplayFishInfo { get; set; } = true;
57 |
58 | /// Position to display fish info when playing fishing minigame
59 | public string FishInfoDisplayPosition { get; set; } = "UpperRight";
60 |
61 | /// Show fish name with fish info
62 | public bool ShowFishName { get; set; } = true;
63 |
64 | /// Show treasure with fish info
65 | public bool ShowTreasure { get; set; } = true;
66 |
67 | /// Show fish info whether uncaught or not
68 | public bool ShowUncaughtFishSpecies { get; set; } = false;
69 |
70 | /// Alway show fish info if current fish is legendary
71 | public bool AlwaysShowLegendaryFish { get; set; } = false;
72 |
73 | /// Add auto-Hook enchantment to fishing rod
74 | public bool AddAutoHookEnchantment { get; set; } = false;
75 |
76 | /// Add Efficient enchantment to fishing rod
77 | public bool AddEfficientEnchantment { get; set; } = false;
78 |
79 | /// Add Master enchantment to fishing rod
80 | public bool AddMasterEnchantment { get; set; } = false;
81 |
82 | /// Add Preserving enchantment to fishing rod
83 | public bool AddPreservingEnchantment { get; set; } = false;
84 |
85 | /// Add Preserving enchantment to fishing rod
86 | public bool OnlyAddEnchantmentWhenHeld { get; set; } = false;
87 |
88 | ///
89 | public string AutomationPresets { get; set; } = "Default";
90 |
91 | /// Auto cast fishing rod on custon preset
92 | public bool AutoCastFishingRod { get; set; } = true;
93 |
94 | /// Auto hook fish rod on custon preset
95 | public bool AutoHookFish { get; set; } = true;
96 |
97 | /// Auto play fishing mini-game on custon preset
98 | public bool AutoPlayMiniGame { get; set; } = true;
99 |
100 | /// Auto close fish popup on custon preset
101 | public bool AutoClosePopup { get; set; } = true;
102 |
103 | /// Auto loot treasure on custon preset
104 | public bool AutoLootTreasure { get; set; } = true;
105 |
106 | /// Shold mod auto attach bait if possible.
107 | public bool AutoAttachBait { get; set; } = false;
108 |
109 | /// Shold mod auto attach bait if possible.
110 | public bool AutoAttachTackles { get; set; } = false;
111 |
112 | /// Whether to pause fishing on given time
113 | public bool EnableAutoPauseFishing { get; set; } = true;
114 |
115 | /// Time to stop fishing
116 | public int PauseFishingTime { get; set; } = 24;
117 |
118 | /// Whether to eat some food if need
119 | public bool EnableAutoEatFood { get; set; } = false;
120 |
121 | /// Amount of energy in percent to find food to eat
122 | public int EnergyPrecentToEat { get; set; } = 0;
123 |
124 | /// Allow to eat fish that you caught
125 | public bool AllowEatingFish { get; set; } = false;
126 | }
127 | }
--------------------------------------------------------------------------------
/FishingAssistant/ModEntry.cs:
--------------------------------------------------------------------------------
1 | using FishingAssistant.Menu;
2 | using StardewModdingAPI;
3 | using StardewModdingAPI.Events;
4 | using StardewValley;
5 | using StardewValley.Menus;
6 | using StardewValley.Tools;
7 |
8 | namespace FishingAssistant
9 | {
10 | partial class ModEntry : Mod
11 | {
12 | private ModConfig Config;
13 | private bool isPause;
14 |
15 | /// The mod entry point, called after the mod is first loaded.
16 | public override void Entry(IModHelper helper)
17 | {
18 | // Initialize mod
19 | Initialize(helper);
20 | }
21 |
22 | /// Raised after the game is launched, right before the first update tick.
23 | private void OnGameLaunched(object sender, GameLaunchedEventArgs e)
24 | {
25 | // read the Config for display position and get list priority for displayOrder
26 | ReloadConfig();
27 | }
28 |
29 | /// Raised after the in-game clock time changes.
30 | private void OnTimeChanged(object sender, TimeChangedEventArgs e)
31 | {
32 | AutoStopFishingOnTime();
33 | }
34 |
35 | /// Raised before the game ends the current day.
36 | /// This happens before it starts setting up the next day and before StardewModdingAPI.Events.IGameLoopEvents.Saving.
37 | private void OnDayStarted(object sender, DayStartedEventArgs e)
38 | {
39 | isForceEnable = false;
40 | hasEnableRequest = false;
41 | hasDisableRequest = false;
42 | }
43 |
44 | /// Raised after the game state is updated (≈60 times per second).
45 | private void OnUpdateTicked(object sender, UpdateTickedEventArgs e)
46 | {
47 | if (!modEnable || !Context.IsWorldReady)
48 | return;
49 |
50 | // Apply infinite bait/tackle
51 | ApplyInfiniteBaitAndTackle();
52 |
53 | if (IsFishingMiniGameReady())
54 | {
55 | //Force fishing minigame result to be perfect
56 | AlwayPerfectResult();
57 |
58 | //Auto play minigame
59 | AutoPlayMiniGame();
60 | }
61 | else
62 | {
63 | //Auto loot item in treasure chest
64 | AutoLootTreasure();
65 | }
66 |
67 | if (Game1.player?.CurrentTool is FishingRod rod)
68 | {
69 | fishingRod = rod;
70 |
71 | if (isPause)
72 | {
73 | //Unpause mod status and get new player data
74 | isPause = false;
75 | GetPlayerData();
76 | }
77 |
78 | AddEnchantment();
79 |
80 | AutoEatFood(ignoreCondition: false);
81 |
82 | // Find bait and tackle add attach to fishing rod
83 | AutoAttachBait();
84 | AutoAttachTackles();
85 |
86 | // Cast fishing rod if possible
87 | AutoCastFishingRod();
88 |
89 | // Force max cast power
90 | MaxCastPower();
91 |
92 | // Make fish instantly bite
93 | InstantFishBite();
94 |
95 | //Auto hook fish when fish bite
96 | AutoHook();
97 |
98 | //Auto close fish popup
99 | AutoCloseFishPopup();
100 | }
101 | else
102 | {
103 | //Change mod status to pasue
104 | isPause = true;
105 | modState = ModState.Pause;
106 | autoCastDelay = defaultAutoCastDelay;
107 | autoClosePopupDelay = defaultAutoClosePopupDelay;
108 | autoLootDelay = defaultAutoLootDelay;
109 |
110 | if (Config.OnlyAddEnchantmentWhenHeld)
111 | fishingRod.ClearEnchantments();
112 | }
113 | }
114 |
115 | /// Raised after a game menu is opened, closed, or replaced.
116 | private void OnMenuChanged(object sender, MenuChangedEventArgs e)
117 | {
118 | //Save config value
119 | if (e.OldMenu is FishingAssistantMenu)
120 | {
121 | Helper.WriteConfig(Config);
122 | ReloadConfig(false);
123 | }
124 |
125 | if (!modEnable)
126 | return;
127 |
128 | // Check if fishing minigame is start
129 | if (e.NewMenu is BobberBar bar)
130 | OnFishingMiniGameStart(bar);
131 |
132 | // Check if fishing minigame is end
133 | if (e.OldMenu is BobberBar)
134 | OnFishingMiniGameEnd();
135 | }
136 |
137 | /// When a menu is open, raised after that menu is drawn to the sprite batch but before it's rendered to the screen.
138 | private void OnRenderMenu(object sender, RenderedActiveMenuEventArgs e)
139 | {
140 | DrawFishInfo();
141 | }
142 |
143 | ///
144 | /// Raised before drawing the HUD (item toolbar, clock, etc) to the screen. The vanilla
145 | /// HUD may be hidden at this point (e.g. because a menu is open). Content drawn
146 | /// to the sprite batch at this point will appear under the HUD.
147 | ///
148 | private void OnRenderingHud(object sender, RenderingHudEventArgs e)
149 | {
150 | DrawModStatus();
151 | }
152 |
153 | /// Raised after the player presses a button on the keyboard, controller, or mouse.
154 | private void OnButtonPressed(object sender, ButtonPressedEventArgs e)
155 | {
156 | if (!Context.IsWorldReady) return;
157 |
158 | //Enable or disable mod
159 | OnEnableModButtonPressed(e);
160 |
161 | //Toggle cast power to max or free
162 | OnCastPowerButtonPressed(e);
163 |
164 | //Toggle catch or ignore treasure when play fishing minigame
165 | OnCatchTreasureButtonPressed(e);
166 |
167 | //Open in-game mod menu
168 | OnToggleMenuButtonPressed(e);
169 | }
170 |
171 | private void OnFishingMiniGameStart(BobberBar bar)
172 | {
173 | bobberBar = bar;
174 | inFishingMiniGame = true;
175 | isCatching = true;
176 | fishPreviewFishId = 0;
177 |
178 | //Overide fish difficulty
179 | OverrideFishDifficult();
180 |
181 | //Make treasure appear every time
182 | AlwayFindTreasure();
183 |
184 | //Instantly catch fish when minigame start
185 | InstantCatchFish();
186 |
187 | //Instantly catch treasure when treasure appear
188 | InstantCatchTreasure();
189 | }
190 |
191 | private void OnFishingMiniGameEnd()
192 | {
193 | //Reset varible value
194 | inFishingMiniGame = false;
195 | isCatching = false;
196 | catchingTreasure = false;
197 |
198 | if (hasDisableRequest)
199 | {
200 | hasDisableRequest = false;
201 | modEnable = false;
202 | modState = ModState.Disable;
203 | }
204 | }
205 | }
206 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUnit
47 | *.VisualState.xml
48 | TestResult.xml
49 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # TeamCity is a build add-in
131 | _TeamCity*
132 |
133 | # DotCover is a Code Coverage Tool
134 | *.dotCover
135 |
136 | # AxoCover is a Code Coverage Tool
137 | .axoCover/*
138 | !.axoCover/settings.json
139 |
140 | # Visual Studio code coverage results
141 | *.coverage
142 | *.coveragexml
143 |
144 | # NCrunch
145 | _NCrunch_*
146 | .*crunch*.local.xml
147 | nCrunchTemp_*
148 |
149 | # MightyMoose
150 | *.mm.*
151 | AutoTest.Net/
152 |
153 | # Web workbench (sass)
154 | .sass-cache/
155 |
156 | # Installshield output folder
157 | [Ee]xpress/
158 |
159 | # DocProject is a documentation generator add-in
160 | DocProject/buildhelp/
161 | DocProject/Help/*.HxT
162 | DocProject/Help/*.HxC
163 | DocProject/Help/*.hhc
164 | DocProject/Help/*.hhk
165 | DocProject/Help/*.hhp
166 | DocProject/Help/Html2
167 | DocProject/Help/html
168 |
169 | # Click-Once directory
170 | publish/
171 |
172 | # Publish Web Output
173 | *.[Pp]ublish.xml
174 | *.azurePubxml
175 | # Note: Comment the next line if you want to checkin your web deploy settings,
176 | # but database connection strings (with potential passwords) will be unencrypted
177 | *.pubxml
178 | *.publishproj
179 |
180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
181 | # checkin your Azure Web App publish settings, but sensitive information contained
182 | # in these scripts will be unencrypted
183 | PublishScripts/
184 |
185 | # NuGet Packages
186 | *.nupkg
187 | # NuGet Symbol Packages
188 | *.snupkg
189 | # The packages folder can be ignored because of Package Restore
190 | **/[Pp]ackages/*
191 | # except build/, which is used as an MSBuild target.
192 | !**/[Pp]ackages/build/
193 | # Uncomment if necessary however generally it will be regenerated when needed
194 | #!**/[Pp]ackages/repositories.config
195 | # NuGet v3's project.json files produces more ignorable files
196 | *.nuget.props
197 | *.nuget.targets
198 |
199 | # Microsoft Azure Build Output
200 | csx/
201 | *.build.csdef
202 |
203 | # Microsoft Azure Emulator
204 | ecf/
205 | rcf/
206 |
207 | # Windows Store app package directories and files
208 | AppPackages/
209 | BundleArtifacts/
210 | Package.StoreAssociation.xml
211 | _pkginfo.txt
212 | *.appx
213 | *.appxbundle
214 | *.appxupload
215 |
216 | # Visual Studio cache files
217 | # files ending in .cache can be ignored
218 | *.[Cc]ache
219 | # but keep track of directories ending in .cache
220 | !?*.[Cc]ache/
221 |
222 | # Others
223 | ClientBin/
224 | ~$*
225 | *~
226 | *.dbmdl
227 | *.dbproj.schemaview
228 | *.jfm
229 | *.pfx
230 | *.publishsettings
231 | orleans.codegen.cs
232 |
233 | # Including strong name files can present a security risk
234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
235 | #*.snk
236 |
237 | # Since there are multiple workflows, uncomment next line to ignore bower_components
238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
239 | #bower_components/
240 |
241 | # RIA/Silverlight projects
242 | Generated_Code/
243 |
244 | # Backup & report files from converting an old project file
245 | # to a newer Visual Studio version. Backup files are not needed,
246 | # because we have git ;-)
247 | _UpgradeReport_Files/
248 | Backup*/
249 | UpgradeLog*.XML
250 | UpgradeLog*.htm
251 | ServiceFabricBackup/
252 | *.rptproj.bak
253 |
254 | # SQL Server files
255 | *.mdf
256 | *.ldf
257 | *.ndf
258 |
259 | # Business Intelligence projects
260 | *.rdl.data
261 | *.bim.layout
262 | *.bim_*.settings
263 | *.rptproj.rsuser
264 | *- [Bb]ackup.rdl
265 | *- [Bb]ackup ([0-9]).rdl
266 | *- [Bb]ackup ([0-9][0-9]).rdl
267 |
268 | # Microsoft Fakes
269 | FakesAssemblies/
270 |
271 | # GhostDoc plugin setting file
272 | *.GhostDoc.xml
273 |
274 | # Node.js Tools for Visual Studio
275 | .ntvs_analysis.dat
276 | node_modules/
277 |
278 | # Visual Studio 6 build log
279 | *.plg
280 |
281 | # Visual Studio 6 workspace options file
282 | *.opt
283 |
284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
285 | *.vbw
286 |
287 | # Visual Studio LightSwitch build output
288 | **/*.HTMLClient/GeneratedArtifacts
289 | **/*.DesktopClient/GeneratedArtifacts
290 | **/*.DesktopClient/ModelManifest.xml
291 | **/*.Server/GeneratedArtifacts
292 | **/*.Server/ModelManifest.xml
293 | _Pvt_Extensions
294 |
295 | # Paket dependency manager
296 | .paket/paket.exe
297 | paket-files/
298 |
299 | # FAKE - F# Make
300 | .fake/
301 |
302 | # CodeRush personal settings
303 | .cr/personal
304 |
305 | # Python Tools for Visual Studio (PTVS)
306 | __pycache__/
307 | *.pyc
308 |
309 | # Cake - Uncomment if you are using it
310 | # tools/**
311 | # !tools/packages.config
312 |
313 | # Tabs Studio
314 | *.tss
315 |
316 | # Telerik's JustMock configuration file
317 | *.jmconfig
318 |
319 | # BizTalk build output
320 | *.btp.cs
321 | *.btm.cs
322 | *.odx.cs
323 | *.xsd.cs
324 |
325 | # OpenCover UI analysis results
326 | OpenCover/
327 |
328 | # Azure Stream Analytics local run output
329 | ASALocalRun/
330 |
331 | # MSBuild Binary and Structured Log
332 | *.binlog
333 |
334 | # NVidia Nsight GPU debugger configuration file
335 | *.nvuser
336 |
337 | # MFractors (Xamarin productivity tool) working folder
338 | .mfractor/
339 |
340 | # Local History for Visual Studio
341 | .localhistory/
342 |
343 | # BeatPulse healthcheck temp database
344 | healthchecksdb
345 |
346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
347 | MigrationBackup/
348 |
349 | # Ionide (cross platform F# VS Code tools) working folder
350 | .ionide/
351 |
--------------------------------------------------------------------------------
/FishingAssistant/Menu/Option/SliderOptionElement.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework;
2 | using Microsoft.Xna.Framework.Graphics;
3 | using StardewValley;
4 | using StardewValley.Menus;
5 | using System;
6 |
7 | namespace FishingAssistant.Menu.Option
8 | {
9 | /// A UI slider for selecting from a range of values.
10 | internal class SliderOptionElement : BaseOptionsElement
11 | {
12 | /*********
13 | ** Fields
14 | *********/
15 |
16 | /// The field label.
17 | private readonly string Label;
18 |
19 | /// The callback to invoke when the value changes.
20 | private readonly Action SetValue;
21 |
22 | /// A callback to invoke when the value changes.
23 | private readonly Action SetValueBool;
24 |
25 | /// The minimum value that can be selected using the field.
26 | private readonly int MinValue;
27 |
28 | /// The maximum value that can be selected using the field.
29 | private readonly int MaxValue;
30 |
31 | /// The current value.
32 | private int Value;
33 |
34 | /// The value's position in the range of values between and .
35 | private float ValuePosition;
36 |
37 | /// Whether the slider should be disabled.
38 | private readonly Func IsDisabled;
39 |
40 | /// Format the display label.
41 | private readonly Func Format;
42 |
43 | /// The pixel width of the slider area.
44 | private int PixelWidth => this.bounds.Width - 10 * Game1.pixelZoom;
45 |
46 | /*********
47 | ** Public methods
48 | *********/
49 |
50 | /// Construct an instance.
51 | /// The field label.
52 | /// The initial value.
53 | /// The maximum value that can be selected using the field.
54 | /// The callback to invoke when the value changes.
55 | /// The minimum value that can be selected using the field.
56 | /// Whether the slider should be disabled.
57 | /// Format the display label.
58 | /// The field width.
59 | public SliderOptionElement(string label, int value, int maxValue, Action setValue, Action setValueBool = null, int minValue = 0, Func disabled = null, Func format = null, int width = 48)
60 | : base(label, -1, -1, width * Game1.pixelZoom, 6 * Game1.pixelZoom, 0)
61 | {
62 | this.Label = label;
63 | this.Value = value;
64 | this.MinValue = minValue;
65 | this.MaxValue = maxValue;
66 | this.SetValue = setValue;
67 | this.SetValueBool = setValueBool;
68 | this.IsDisabled = disabled ?? (() => false);
69 | this.Format = format ?? (v => v.ToString());
70 |
71 | this.ValuePosition = this.GetRangePosition();
72 | }
73 |
74 | /// Handle the player holding the left mouse button.
75 | /// The cursor's X pixel position.
76 | /// The cursor's Y pixel position.
77 | public override void leftClickHeld(int x, int y)
78 | {
79 | if (this.greyedOut)
80 | return;
81 |
82 | base.leftClickHeld(x, y);
83 |
84 | this.ValuePosition = GetRangePosition(x, this.bounds.X, this.bounds.X + this.PixelWidth);
85 | this.Value = GetValueAtPosition(this.ValuePosition, this.MinValue, this.MaxValue);
86 | }
87 |
88 | /// Handle the player clicking the left mouse button.
89 | /// The cursor's X pixel position.
90 | /// The cursor's Y pixel position.
91 | public override void receiveLeftClick(int x, int y)
92 | {
93 | if (this.greyedOut)
94 | return;
95 | base.receiveLeftClick(x, y);
96 | this.leftClickHeld(x, y);
97 | }
98 |
99 | /// Handle the player releasing the left mouse button.
100 | /// The cursor's X pixel position.
101 | /// The cursor's Y pixel position.
102 | public override void leftClickReleased(int x, int y)
103 | {
104 | this.ValuePosition = this.GetRangePosition(); // snap to value position
105 | this.SetValue(this.Value);
106 | if (SetValueBool != null)
107 | this.SetValueBool(false);
108 | }
109 |
110 | /// Draw the component to the screen.
111 | /// The sprite batch being drawn.
112 | /// The X position at which to draw, relative to the bounds.
113 | /// The Y position at which to draw, relative to the bounds.
114 | /// The menu drawing the component.
115 | public override void draw(SpriteBatch spriteBatch, int slotX, int slotY, IClickableMenu context = null)
116 | {
117 | this.label = $"{this.Label}: {this.Format(this.Value)}";
118 | this.greyedOut = this.IsDisabled();
119 |
120 | base.draw(spriteBatch, slotX + this.GetOffsetX(), slotY, context);
121 |
122 | int sliderOffsetX = GetValueAtPosition(this.ValuePosition, 0, this.PixelWidth);
123 | IClickableMenu.drawTextureBox(spriteBatch, Game1.mouseCursors, OptionsSlider.sliderBGSource, slotX + this.bounds.X, slotY + this.bounds.Y, this.bounds.Width, this.bounds.Height, Color.White * (this.greyedOut ? 0.33f : 1f), Game1.pixelZoom, false);
124 | spriteBatch.Draw(Game1.mouseCursors, new Vector2(slotX + this.bounds.X + sliderOffsetX, slotY + this.bounds.Y), OptionsSlider.sliderButtonRect, Color.White * (this.greyedOut ? 0.33f : 1f), 0.0f, Vector2.Zero, Game1.pixelZoom, SpriteEffects.None, 0.9f);
125 | }
126 |
127 | /*********
128 | ** Private methods
129 | *********/
130 |
131 | /// Get the 's fractional position, as a value between 0 () and 1 ().
132 | private float GetRangePosition()
133 | {
134 | return GetRangePosition(this.Value, this.MinValue, this.MaxValue);
135 | }
136 |
137 | /****
138 | ** Math helpers
139 | ****/
140 |
141 | /// Get a value's fractional position within a range, as a value between 0 () and 1 ().
142 | /// The value within the range.
143 | /// The minimum value.
144 | /// The maximum value.
145 | public static float GetRangePosition(int value, int minValue, int maxValue)
146 | {
147 | float position = (value - minValue) / (float)(maxValue - minValue);
148 | return MathHelper.Clamp(position, 0, 1);
149 | }
150 |
151 | /// Get the value from a position within a range.
152 | /// The position within the range, where 0 is the minimum value and 1 is the maximum value.
153 | /// The minimum value.
154 | /// The maximum value.
155 | public static int GetValueAtPosition(float position, int minValue, int maxValue)
156 | {
157 | float value = position * (maxValue - minValue) + minValue;
158 | return (int)MathHelper.Clamp(value, minValue, maxValue);
159 | }
160 | }
161 | }
--------------------------------------------------------------------------------
/FishingAssistant/Framework/SFishingRod.cs:
--------------------------------------------------------------------------------
1 | using FishingAssistant.Framework;
2 | using StardewModdingAPI;
3 | using StardewValley;
4 | using StardewValley.Tools;
5 | using System;
6 |
7 | namespace FishingAssistant
8 | {
9 | internal partial class ModEntry : Mod
10 | {
11 | private FishingRod fishingRod;
12 |
13 | private bool IsRodBobberStillInAir
14 | {
15 | get
16 | {
17 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
18 | return fishingRod.castedButBobberStillInAir;
19 | }
20 | }
21 |
22 | private bool IsRodCasting
23 | {
24 | get
25 | {
26 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
27 | return fishingRod.isCasting;
28 | }
29 | }
30 |
31 | private bool IsRodFishCaught
32 | {
33 | get
34 | {
35 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
36 | return fishingRod.fishCaught;
37 | }
38 | set
39 | {
40 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
41 | fishingRod.fishCaught = value;
42 | }
43 | }
44 |
45 | private bool IsRodFishing
46 | {
47 | get
48 | {
49 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
50 | return fishingRod.isFishing;
51 | }
52 | }
53 |
54 | private bool IsRodHit
55 | {
56 | get
57 | {
58 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
59 | return fishingRod.hit;
60 | }
61 | }
62 |
63 | private bool IsRodInUse
64 | {
65 | get
66 | {
67 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
68 | return fishingRod.inUse();
69 | }
70 | }
71 |
72 | private bool IsRodNibbing
73 | {
74 | get
75 | {
76 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
77 | return fishingRod.isNibbling;
78 | }
79 | }
80 |
81 | private bool IsRodPullingOutOfWater
82 | {
83 | get
84 | {
85 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
86 | return fishingRod.pullingOutOfWater;
87 | }
88 | }
89 |
90 | private bool IsRodReeling
91 | {
92 | get
93 | {
94 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
95 | return fishingRod.isReeling;
96 | }
97 | }
98 |
99 | private bool IsRodShowingTreasure
100 | {
101 | get
102 | {
103 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
104 | return fishingRod.showingTreasure;
105 | }
106 | set
107 | {
108 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
109 | fishingRod.showingTreasure = value;
110 | }
111 | }
112 |
113 | private bool IsRodTimingCasting
114 | {
115 | get
116 | {
117 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
118 | return fishingRod.isTimingCast;
119 | }
120 | }
121 |
122 | private bool IsRodTreasureCaught
123 | {
124 | get
125 | {
126 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
127 | return fishingRod.treasureCaught;
128 | }
129 | }
130 |
131 | private float RodCastPower
132 | {
133 | set
134 | {
135 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
136 | fishingRod.castingPower = value;
137 | }
138 | }
139 |
140 | private bool RodCaughtDoubleFish
141 | {
142 | get
143 | {
144 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
145 | return Helper.Reflection.GetField(fishingRod, KeyHelper.caughtDoubleFish, true).GetValue();
146 | }
147 | set
148 | {
149 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
150 | Helper.Reflection.GetField(fishingRod, KeyHelper.caughtDoubleFish, true).SetValue(value);
151 | }
152 | }
153 |
154 | private int RodFishQuality
155 | {
156 | get
157 | {
158 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
159 | return Helper.Reflection.GetField(fishingRod, KeyHelper.fishQuality, true).GetValue();
160 | }
161 | set
162 | {
163 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
164 | Helper.Reflection.GetField(fishingRod, KeyHelper.fishQuality, true).SetValue(value);
165 | }
166 | }
167 |
168 | private bool RodFromFishPond
169 | {
170 | get
171 | {
172 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
173 | return Helper.Reflection.GetField(fishingRod, KeyHelper.fromFishPond, true).GetValue();
174 | }
175 | set
176 | {
177 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
178 | Helper.Reflection.GetField(fishingRod, KeyHelper.fromFishPond, true).SetValue(value);
179 | }
180 | }
181 |
182 | private string RodItemCategory
183 | {
184 | get
185 | {
186 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
187 | return Helper.Reflection.GetField(fishingRod, KeyHelper.itemCategory, true).GetValue();
188 | }
189 | set
190 | {
191 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
192 | Helper.Reflection.GetField(fishingRod, KeyHelper.itemCategory, true).SetValue(value);
193 | }
194 | }
195 |
196 | private float RodTimeUntilFishBite
197 | {
198 | get
199 | {
200 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
201 | return fishingRod.timeUntilFishingBite;
202 | }
203 | set
204 | {
205 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
206 | fishingRod.timeUntilFishingBite = value;
207 | }
208 | }
209 |
210 | private int RodWhichFish
211 | {
212 | get
213 | {
214 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
215 | return Helper.Reflection.GetField(fishingRod, KeyHelper.whichFish, true).GetValue();
216 | }
217 | set
218 | {
219 | if (fishingRod == null) throw new NullReferenceException(nameof(fishingRod));
220 | Helper.Reflection.GetField(fishingRod, KeyHelper.whichFish, true).SetValue(value);
221 | }
222 | }
223 |
224 | /// Is player able to cast fishing rod
225 | /// True if player can cast fishing rod
226 | private bool RodIsNotInUse()
227 | {
228 | return Context.CanPlayerMove && Game1.activeClickableMenu == null && !fishingRod.inUse();
229 | }
230 |
231 | /// Is fish bite or not
232 | /// True if fish bite
233 | private bool IsRodCanHook()
234 | {
235 | return IsRodNibbing && !IsRodReeling && !IsRodHit && !IsRodPullingOutOfWater && !IsRodFishCaught;
236 | }
237 |
238 | /// Is player currenly showing fish
239 | /// True if fish popup is show
240 | private bool IsRodShowingFish()
241 | {
242 | return !Context.CanPlayerMove && IsRodFishCaught && IsRodInUse && !IsRodCasting && !IsRodTimingCasting && !IsRodReeling && !IsRodPullingOutOfWater && !IsRodShowingTreasure;
243 | }
244 | }
245 | }
--------------------------------------------------------------------------------
/FishingAssistant/Component/FishPreview.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework;
2 | using Microsoft.Xna.Framework.Graphics;
3 | using StardewModdingAPI;
4 | using StardewValley;
5 | using StardewValley.Menus;
6 | using StardewValley.Tools;
7 | using System;
8 | using System.Collections.Generic;
9 | using Object = StardewValley.Object;
10 |
11 | namespace FishingAssistant
12 | {
13 | internal partial class ModEntry : Mod
14 | {
15 | private bool isCatching = false;
16 | private int fishPreviewFishId = 0;
17 | private Object fishSprite;
18 | private Object treasureSprite;
19 | private bool showFish;
20 | private bool showText;
21 | private string textValue;
22 | private IList displayOrder;
23 | private Vector2 textSize;
24 | private int margin = 18;
25 | private int spriteSize = 64;
26 | private float scale = 0.7f;
27 | private int boxwidth;
28 | private int boxheight;
29 | private int treasureSpacing = 50;
30 | private int treasureOffset = 8;
31 |
32 | private void DrawFishInfo()
33 | {
34 | if (Game1.player == null || !Game1.player.IsLocalPlayer || !Config.DisplayFishInfo)
35 | return;
36 |
37 | if (Game1.activeClickableMenu is BobberBar bar && isCatching)
38 | {
39 | // stop drawing on fadeOut
40 | if (BarFadeOut)
41 | return;
42 |
43 | // figure out which fish is being caught
44 | int newFishId = BarWhichFish;
45 |
46 | // check if fish has changed somehow. If yes, re-make the fish sprite and its display text.
47 | GetFishData(newFishId);
48 |
49 | // call a function to position and draw the box
50 | DrawFishDisplay(displayOrder, bar);
51 | }
52 | }
53 |
54 | private void GetFishData(int newFishId)
55 | {
56 | if (newFishId != fishPreviewFishId) // catching a new fish OR the fish species has changed mid-cast
57 | {
58 | fishPreviewFishId = newFishId;
59 | Monitor.Log($"Currently catching: {fishPreviewFishId}", LogLevel.Trace);
60 |
61 | // save fish object to use in drawing // check for errors?
62 | fishSprite = new Object(fishPreviewFishId, 1);
63 |
64 | // determine if species has been caught before
65 | bool caughtSpecies = Game1.player.fishCaught.ContainsKey(fishPreviewFishId) && Game1.player.fishCaught[fishPreviewFishId][0] > 0;
66 |
67 | // is it a legendary fish?
68 | bool isLegendary = Helper.Reflection.GetMethod(typeof(FishingRod), "isFishBossFish").Invoke(fishPreviewFishId);
69 | Monitor.Log($"Catching legendary fish? {isLegendary}", LogLevel.Trace);
70 |
71 | // determine value of showFish value
72 | showFish = Config.ShowUncaughtFishSpecies || caughtSpecies || (Config.AlwaysShowLegendaryFish && isLegendary);
73 |
74 | // determine value of showText value
75 | showText = Config.ShowFishName;
76 |
77 | // determine text to show if true
78 | if (showText && showFish)
79 | {
80 | textValue = fishSprite.DisplayName; // does it need translation help? (Seems to work with French already)
81 | this.Monitor.Log($"Fish name: {textValue}", LogLevel.Trace);
82 | }
83 | else
84 | {
85 | textValue = "???";
86 | }
87 |
88 | // determine width and height of display box
89 | boxwidth = 160; boxheight = 100;
90 |
91 | textSize = Game1.dialogueFont.MeasureString(textValue) * scale;
92 |
93 | if (showText && showFish) { boxwidth = Math.Max(160, (2 * margin) + (int)textSize.X); }
94 | if (showText) { boxheight += (int)textSize.Y; }
95 | }
96 | }
97 |
98 | private void DrawFishDisplay(IList positions, BobberBar bar)
99 | {
100 | // call a function to determine the x and y coords
101 | DetermineCoordinates(positions, bar, out int x, out int y);
102 | // call a function to draw the box
103 | DrawAtCoordinates((int)(x * (Game1.options.zoomLevel / Game1.options.uiScale)), (int)(y * (Game1.options.zoomLevel / Game1.options.uiScale)));
104 | }
105 |
106 | private void DetermineCoordinates(IList positions, BobberBar bar, out int x, out int y)
107 | {
108 | // define offset values
109 | int xLeftOffset = -32; int xCenterOffset = 32; int xRightOffset = 80;
110 | int yTopOffset = -32; int yUpperOffset = 0; int yLowerOffset = -40; int yBottomOffset = -12;
111 |
112 | // determine x and y positions
113 | foreach (string position in positions)
114 | {
115 | // set the correct display coordinates from position values in order of priority
116 | switch (position)
117 | {
118 | case "Top":
119 | x = bar.xPositionOnScreen + (bar.width / 2) - (boxwidth / 2) + xCenterOffset;
120 | y = bar.yPositionOnScreen - boxheight + yTopOffset;
121 | break;
122 |
123 | case "UpperRight":
124 | x = bar.xPositionOnScreen + bar.width + xRightOffset;
125 | y = bar.yPositionOnScreen + yUpperOffset;
126 | break;
127 |
128 | case "UpperLeft":
129 | x = bar.xPositionOnScreen - boxwidth + xLeftOffset;
130 | y = bar.yPositionOnScreen + yUpperOffset;
131 | break;
132 |
133 | case "Bottom":
134 | x = bar.xPositionOnScreen + (bar.width / 2) - (boxwidth / 2) + xCenterOffset;
135 | y = bar.yPositionOnScreen + bar.height + yBottomOffset;
136 | break;
137 |
138 | case "LowerRight":
139 | x = bar.xPositionOnScreen + bar.width + xRightOffset;
140 | y = bar.yPositionOnScreen + bar.height - boxheight + yLowerOffset;
141 | break;
142 |
143 | case "LowerLeft":
144 | x = bar.xPositionOnScreen - boxwidth + xLeftOffset;
145 | y = bar.yPositionOnScreen + bar.height - boxheight + yLowerOffset;
146 | break;
147 |
148 | default:
149 | // default to UpperRight position
150 | x = bar.xPositionOnScreen + bar.width + xRightOffset;
151 | y = bar.yPositionOnScreen + yUpperOffset;
152 | //this.Monitor.Log($"Invalid position {position} listed in displayOrder.", LogLevel.Debug);
153 | break;
154 | }
155 |
156 | // if the box display is in bounds, break the loop. Otherwise proceed to alternative display position(s).
157 | if (x >= 0 && y >= 0 && x + boxwidth <= Game1.viewport.Width && y + boxheight <= Game1.viewport.Height)
158 | return;
159 | }
160 | // if no suitable location found in foreach, default to UpperRight position
161 | x = bar.xPositionOnScreen + bar.width + xRightOffset;
162 | y = bar.yPositionOnScreen + yUpperOffset;
163 | //this.Monitor.Log($"No suitable coordinate position found in displayOrder.", LogLevel.Debug);
164 | }
165 |
166 | private void DrawAtCoordinates(int x, int y)
167 | {
168 | // draw box of height and width at location
169 | IClickableMenu.drawTextureBox(Game1.spriteBatch, x, y, boxwidth, boxheight, Color.White);
170 |
171 | //Calculate draw position for fish
172 | Vector2 drawPos;
173 | if (Config.ShowTreasure && BarHasTreasure && !BarTreasureCaught)
174 | drawPos = new Vector2(x + (boxwidth / 2) - (spriteSize / 2) - (treasureSpacing / 2) + treasureOffset, y + margin);
175 | else
176 | drawPos = new Vector2(x + (boxwidth / 2) - (spriteSize / 2), y + margin);
177 |
178 | if (showFish) // if showFish, draw fish in normal color
179 | fishSprite.drawInMenu(Game1.spriteBatch, drawPos, 1.0f, 1.0f, 1.0f, StackDrawType.Hide);
180 | else // else (if not showFish), draw fish in black color
181 | fishSprite.drawInMenu(Game1.spriteBatch, drawPos, 1.0f, 1.0f, 1.0f, StackDrawType.Hide, Color.Black * 0.8f, true);
182 |
183 | if (showText) // if showText, center the text x below the fish
184 | Game1.spriteBatch.DrawString(Game1.dialogueFont, textValue, new Vector2(x + (boxwidth / 2) - ((int)textSize.X / 2), y + spriteSize + margin), Color.Black, 0f, Vector2.Zero, scale, SpriteEffects.None, 0f);
185 |
186 | // if show treasure draw treasure with fish icon
187 | if (Config.ShowTreasure && BarHasTreasure && !BarTreasureCaught)
188 | {
189 | treasureSprite = new Object(693, 1);
190 | treasureSprite.drawInMenu(Game1.spriteBatch, new Vector2(x + (boxwidth / 2) - (spriteSize / 2) + (treasureSpacing / 2) + treasureOffset, y + margin), 1.0f, 1.0f, 1.0f, StackDrawType.Hide);
191 | }
192 | }
193 | }
194 | }
--------------------------------------------------------------------------------
/FishingAssistant/README.md:
--------------------------------------------------------------------------------
1 | ## Fishing Assistant
2 | Simple ```Stardew Valley Mod``` which allows you to ```automatically catching fish``` and customize fishing mechanics by making it easier or harder even cheating it. this mod comes with additional features like fish and treasure preview, auto-stop fishing at night or low stamina, and more to come.
3 |
4 | ## Feature
5 | List of currently available mod features
6 | - Automation mode (cast fishing rod, hook fish, play mini-games, loot treasure).
7 | - Prevent players from fishing when stamina is low.
8 | - Auto-stop fishing at night (time can be changed in the config file).
9 | - Preview current fish and show you if this round has a treasure.
10 | - Configurable cheat in a config file.
11 |
12 | ## Requirements
13 | SMAPI - Stardew Modding API. [SMAPI Homepage](https://smapi.io/) | [Nexus](https://www.nexusmods.com/stardewvalley/mods/2400)
14 |
15 | ## Installation
16 |
17 | - Decompress the downloaded zip file.
18 | - Move the `FishingAssistant` folder to the `Mods` directory of your StardewValley installation. If you dont have a `Mods` directory, please ensure you have already downloaded and installed **SMAPI** from the [SMAPI Homepage](https://smapi.io/)| [Nexus](https://www.nexusmods.com/stardewvalley/mods/2400) and have launched the game at least once after its installation.
19 |
20 | ## Usage
21 | When first run, the mod includes a default configuration that disable all cheat. You can enable this mod in-game by pressing `F5` button on keyboard. Force cast power to max by pressing `F6` button on keyboard. Catch or ignore treasure by pressing `F7` button on keyboard and reload the new configuration value by pressing `F8` button on keyboard.
22 |
23 | To further tweak the fishing mechanics, you need to edit the `Mod configuration file` located in the `mod's` directory. This file is created automatically once the game has been launched at least once with the mod installed. Please refer to the **Configuration** section for details on how to further tweak the mod.
24 |
25 | ## Remarks
26 | - This mod doesn't affect the achievements you can get through Steam, fished counts will still increment as normal when a fish is reeled.
27 | - The mod is designed to be compatible with the **Multiplayer/Coop mode** of the game. **This is still being tested**, May have problems playing the animation of the characters on other players.
28 | - Bug report are available at the Nexus mod page [link](https://www.nexusmods.com/stardewvalley/mods/5815?tab=bugs). Bug fixes are based upon availability, priority and problem level
29 |
30 | ## Configuration
31 | The `configuration file` is located on the mod's folder under the StardewValley installation directory, and it's automatically created the first time the game runs with this mod installed.
32 |
33 | ### EnableModButton
34 | **Default value:** `F5`
35 | **Possible values:** See `Modding:Player Guide/Key Bindings` on Stardew valley wiki. [Here](https://stardewcommunitywiki.com/Modding:Player_Guide/Key_Bindings#Button_codes)
36 |
37 | ```
38 | A button to enable this mod, press again for disable.
39 | ```
40 |
41 | ### CastPowerButton
42 | **Default value:** `F6`
43 | **Possible values:** See `Modding:Player Guide/Key Bindings` on Stardew valley wiki. [Here](https://stardewcommunitywiki.com/Modding:Player_Guide/Key_Bindings#Button_codes)
44 |
45 | ```
46 | A button for force fishing rod cast power to max, press again for disable.
47 | ```
48 |
49 | ### CatchTreasureButton
50 | **Default value:** `F7`
51 | **Possible values:** See `Modding:Player Guide/Key Bindings` on Stardew valley wiki. [Here](https://stardewcommunitywiki.com/Modding:Player_Guide/Key_Bindings#Button_codes)
52 |
53 | ```
54 | A button for toggle catch or ignore treasure when treasure appeared.
55 | ```
56 |
57 | ### OpenMenuButton
58 | **Default value:** `F8`
59 | **Possible values:** See `Modding:Player Guide/Key Bindings` on Stardew valley wiki. [Here](https://stardewcommunitywiki.com/Modding:Player_Guide/Key_Bindings#Button_codes)
60 |
61 | ```
62 | A button for open in-game config menu.
63 | ```
64 |
65 | ### AlwaysPerfect
66 | **Default value:** `false`
67 | **Possible values:** `true | false`
68 |
69 | ```
70 | Making the result of fishing always perfect, even if it wasn't.
71 | ```
72 |
73 | ### AlwaysFindTreasure
74 | **Default value:** `false`
75 | **Possible values:** `true | false`
76 |
77 | ```
78 | Causing you to find a treasure every time you fish.
79 | ```
80 |
81 | ### InstantFishBite
82 | **Default value:** `false`
83 | **Possible values:** `true | false`
84 |
85 | ```
86 | Fish will instantly bite when you throw a fishing rod.
87 | ```
88 |
89 | ### InstantCatchFish
90 | **Default value:** `false`
91 | **Possible values:** `true | false`
92 |
93 | ```
94 | Instantly catch fish when fish hooked.
95 | ```
96 |
97 | ### InstantCatchTreasure
98 | **Default value:** `false`
99 | **Possible values:** `true | false`
100 |
101 | ```
102 | Instantly catch treasure when treasure appeared.
103 | ```
104 |
105 | ### InfiniteTackle
106 | **Default value:** `false`
107 | **Possible values:** `true | false`
108 |
109 | ```
110 | Make your fishing tackle last long forever.
111 | ```
112 |
113 | ### InfiniteBait
114 | **Default value:** `false`
115 | **Possible values:** `true | false`
116 |
117 | ```
118 | Make your fishing bait last long forever.
119 | ```
120 |
121 | ### FishDifficultyMultiplier
122 | **Default value:** `1`
123 | **Possible values:** `0 - 1 to lower difficulty, or more than 1 to increase it.`
124 |
125 | ```
126 | A multiplier applied to the fish difficulty.
127 | ```
128 |
129 | ### FishDifficultyAdditive
130 | **Default value:** `0`
131 | **Possible values:** `< 0 to lower difficulty, or > 0 to increase it.`
132 |
133 | ```
134 | A value added to the fish difficulty.
135 | ```
136 |
137 | ### AlwaysCatchDoubleFish
138 | **Default value:** `false`
139 | **Possible values:** `true | false`
140 |
141 | ```
142 | Make you catch double fish every time.
143 | ```
144 |
145 | ### ModStatusDisplayPosition
146 | **Default value:** `Left`
147 | **Possible values:** `Left | Right`
148 |
149 | ```
150 | Position of mod status info
151 | ```
152 |
153 | ### DisplayFishInfo
154 | **Default value:** `true`
155 | **Possible values:** `true | false`
156 |
157 | ```
158 | Should mod show fish info while catching fish?
159 | ```
160 |
161 | ### FishInfoDisplayPosition
162 | **Default value:** `"UpperRight"`
163 | **Possible values:** `"Top" | "UpperRight" | "UpperLeft" | "Bottom" | "LowerRight" | "LowerLeft"`
164 |
165 | ```
166 | Position to display fish info when playing a fishing minigame.
167 | ```
168 |
169 | ### ShowFishName
170 | **Default value:** `true`
171 | **Possible values:** `true | false`
172 |
173 | ```
174 | Shows the text of the fish name under the icon.
175 | ```
176 |
177 | ### ShowTreasure
178 | **Default value:** `true`
179 | **Possible values:** `true | false`
180 |
181 | ```
182 | Show treasure icon with fish info.
183 | ```
184 |
185 | ### ShowUncaughtFishSpecies
186 | **Default value:** `false`
187 | **Possible values:** `true | false`
188 |
189 | ```
190 | Show a preview for all fish species, even ones you have never caught.
191 | ```
192 |
193 | ### AlwaysShowLegendaryFish
194 | **Default value:** `false`
195 | **Possible values:** `true | false`
196 |
197 | ```
198 | Show a preview for legendary fish.
199 | ```
200 |
201 | ### AddAutoHookEnchantment
202 | **Default value:** `false`
203 | **Possible values:** `true | false`
204 |
205 | ```
206 | Add Auto-Hook enchantment to fishing rod.
207 | ```
208 |
209 | ### AddEfficientEnchantment
210 | **Default value:** `false`
211 | **Possible values:** `true | false`
212 |
213 | ```
214 | Add Efficient enchantment to fishing rod.
215 | ```
216 |
217 | ### AddMasterEnchantment
218 | **Default value:** `false`
219 | **Possible values:** `true | false`
220 |
221 | ```
222 | Add Master enchantment to fishing rod.
223 | ```
224 |
225 | ### AddPreservingEnchantment
226 | **Default value:** `false`
227 | **Possible values:** `true | false`
228 |
229 | ```
230 | Add Preserving enchantment to fishing rod.
231 | ```
232 |
233 | ### OnlyAddEnchantmentWhenHeld
234 | **Default value:** `false`
235 | **Possible values:** `true | false`
236 |
237 | ```
238 | Remove all enchantment when fishing rod is switching out.
239 | ```
240 |
241 | ### AutomationPresets
242 | **Default value:** `"Default"`
243 | **Possible values:** `"Default" | "Custom" | "Disable"`
244 |
245 | ```
246 | What automation preset that this mod should use.
247 | ```
248 |
249 | ### AutoCastFishingRod
250 | **Default value:** `true`
251 | **Possible values:** `true | false`
252 |
253 | ```
254 | Should mod do auto cast fishing rod.
255 | ```
256 |
257 | ### AutoHookFish
258 | **Default value:** `true`
259 | **Possible values:** `true | false`
260 |
261 | ```
262 | Should mod do auto hook fish.
263 | ```
264 |
265 | ### AutoPlayMiniGame
266 | **Default value:** `true`
267 | **Possible values:** `true | false`
268 |
269 | ```
270 | Should mod do auto play fishing mini-game.
271 | ```
272 |
273 | ### AutoClosePopup
274 | **Default value:** `true`
275 | **Possible values:** `true | false`
276 |
277 | ```
278 | Should mod do auto close popup.
279 | ```
280 |
281 | ### AutoLootTreasure
282 | **Default value:** `true`
283 | **Possible values:** `true | false`
284 |
285 | ```
286 | Should mod do auto loot treasure.
287 | ```
288 |
289 | ### AutoAttachBait
290 | **Default value:** `false`
291 | **Possible values:** `true | false`
292 |
293 | ```
294 | Should mod auto attach bait for you.
295 | ```
296 |
297 | ### AutoAttachTackles
298 | **Default value:** `false`
299 | **Possible values:** `true | false`
300 |
301 | ```
302 | Should mod auto attach tackle for you.
303 | ```
304 |
305 | ### EnableAutoPauseFishing
306 | **Default value:** `true`
307 | **Possible values:** `true | false`
308 |
309 | ```
310 | Should mod auto pause fishing on night.
311 | ```
312 |
313 | ### PauseFishingTime
314 | **Default value:** `24`
315 | **Possible values:** `6 - 25`
316 |
317 | ```
318 | Time to stop fishing.
319 | ```
320 |
321 | ### EnableAutoEatFood
322 | **Default value:** `false`
323 | **Possible values:** `true | false`
324 |
325 | ```
326 | Whether to eat some food if need.
327 | ```
328 |
329 | ### EnergyPrecentToEat
330 | **Default value:** `0`
331 | **Possible values:** `0 - 95`
332 |
333 | ```
334 | Amount of energy in percent to find food to eat.
335 | ```
336 |
337 | ### AllowEatingFish
338 | **Default value:** `false`
339 | **Possible values:** `true | false`
340 |
341 | ```
342 | Allow to eat fish that you caught.
343 | ```
344 |
345 | ## Open-Source commitment
346 | This mod is **Open-Source**, which means its code is public, freely-available, and covered by an open-source license.
347 |
348 | For more details about why OpenSourcing is important on StardewValley mods see the Open-Source Wiki entry on [Stardew Valley Wiki](https://stardewvalleywiki.com/Modding:Open_source).
349 |
350 | # Licensing
351 | This mod is licensed under the GNU Lesser General Public License v3.0 License. For more information see [LGPL License details](https://github.com/KilZenc/Stardew-SMAPI-Mods/blob/main/LICENSE)
352 |
--------------------------------------------------------------------------------
/FishingAssistant/Framework/SBobberBar.cs:
--------------------------------------------------------------------------------
1 | using FishingAssistant.Framework;
2 | using Microsoft.Xna.Framework;
3 | using StardewModdingAPI;
4 | using StardewValley;
5 | using StardewValley.Menus;
6 | using System;
7 |
8 | namespace FishingAssistant
9 | {
10 | internal partial class ModEntry : Mod
11 | {
12 | private BobberBar bobberBar;
13 |
14 | private float BarBobberPosition
15 | {
16 | get
17 | {
18 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
19 | return Helper.Reflection.GetField(bobberBar, KeyHelper.bobberPosition, true).GetValue();
20 | }
21 | set
22 | {
23 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
24 | Helper.Reflection.GetField(bobberBar, KeyHelper.bobberPosition, true).SetValue(value);
25 | }
26 | }
27 |
28 | private bool BarBossFish
29 | {
30 | get
31 | {
32 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
33 | return Helper.Reflection.GetField(bobberBar, KeyHelper.bossFish, true).GetValue();
34 | }
35 | set
36 | {
37 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
38 | Helper.Reflection.GetField(bobberBar, KeyHelper.bossFish, true).SetValue(value);
39 | }
40 | }
41 |
42 | private float BarDifficulty
43 | {
44 | get
45 | {
46 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
47 | return Helper.Reflection.GetField(bobberBar, KeyHelper.difficulty, true).GetValue();
48 | }
49 | set
50 | {
51 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
52 | Helper.Reflection.GetField(bobberBar, KeyHelper.difficulty, true).SetValue(value);
53 | }
54 | }
55 |
56 | private float BarDistanceFromCatching
57 | {
58 | get
59 | {
60 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
61 | return Helper.Reflection.GetField(bobberBar, KeyHelper.distanceFromCatching, true).GetValue();
62 | }
63 | set
64 | {
65 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
66 | Helper.Reflection.GetField(bobberBar, KeyHelper.distanceFromCatching, true).SetValue(value);
67 | }
68 | }
69 |
70 | private bool BarFadeOut
71 | {
72 | get
73 | {
74 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
75 | return Helper.Reflection.GetField(bobberBar, KeyHelper.fadeOut, true).GetValue();
76 | }
77 | set
78 | {
79 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
80 | Helper.Reflection.GetField(bobberBar, KeyHelper.fadeOut, true).SetValue(value);
81 | }
82 | }
83 |
84 | private int BarFishQuality
85 | {
86 | get
87 | {
88 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
89 | return Helper.Reflection.GetField(bobberBar, KeyHelper.fishQuality, true).GetValue();
90 | }
91 | set
92 | {
93 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
94 | Helper.Reflection.GetField(bobberBar, KeyHelper.fishQuality, true).SetValue(value);
95 | }
96 | }
97 |
98 | private int BarFishSize
99 | {
100 | get
101 | {
102 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
103 | return Helper.Reflection.GetField(bobberBar, KeyHelper.fishSize, true).GetValue();
104 | }
105 | set
106 | {
107 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
108 | Helper.Reflection.GetField(bobberBar, KeyHelper.fishSize, true).SetValue(value);
109 | }
110 | }
111 |
112 | private bool BarFromFishPond
113 | {
114 | get
115 | {
116 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
117 | return Helper.Reflection.GetField(bobberBar, KeyHelper.fromFishPond, true).GetValue();
118 | }
119 | set
120 | {
121 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
122 | Helper.Reflection.GetField(bobberBar, KeyHelper.fromFishPond, true).SetValue(value);
123 | }
124 | }
125 |
126 | private bool BarHasTreasure
127 | {
128 | get
129 | {
130 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
131 | return Helper.Reflection.GetField(bobberBar, KeyHelper.treasure, true).GetValue();
132 | }
133 | set
134 | {
135 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
136 | Helper.Reflection.GetField(bobberBar, KeyHelper.treasure, true).SetValue(value);
137 | }
138 | }
139 |
140 | private int BarHeight // Hardcoded Max: 568
141 | {
142 | get
143 | {
144 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
145 | return Helper.Reflection.GetField(bobberBar, KeyHelper.bobberBarHeight, true).GetValue();
146 | }
147 | set
148 | {
149 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
150 | Helper.Reflection.GetField(bobberBar, KeyHelper.bobberBarHeight, true).SetValue(value);
151 | }
152 | }
153 |
154 | private bool BarPerfect
155 | {
156 | get
157 | {
158 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
159 | return Helper.Reflection.GetField(bobberBar, KeyHelper.perfect, true).GetValue();
160 | }
161 | set
162 | {
163 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
164 | Helper.Reflection.GetField(bobberBar, KeyHelper.perfect, true).SetValue(value);
165 | }
166 | }
167 |
168 | private float BarPosition
169 | {
170 | get
171 | {
172 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
173 | return Helper.Reflection.GetField(bobberBar, KeyHelper.bobberBarPos, true).GetValue();
174 | }
175 | set
176 | {
177 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
178 | Helper.Reflection.GetField(bobberBar, KeyHelper.bobberBarPos, true).SetValue(value);
179 | }
180 | }
181 |
182 | private float BarTreasureCatchLevel
183 | {
184 | get
185 | {
186 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
187 | return Helper.Reflection.GetField(bobberBar, KeyHelper.treasureCatchLevel, true).GetValue();
188 | }
189 | set
190 | {
191 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
192 | Helper.Reflection.GetField(bobberBar, KeyHelper.treasureCatchLevel, true).SetValue(value);
193 | }
194 | }
195 |
196 | private bool BarTreasureCaught
197 | {
198 | get
199 | {
200 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
201 | return Helper.Reflection.GetField(bobberBar, KeyHelper.treasureCaught, true).GetValue();
202 | }
203 | set
204 | {
205 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
206 | Helper.Reflection.GetField(bobberBar, KeyHelper.treasureCaught, true).SetValue(value);
207 | }
208 | }
209 |
210 | private float BarTreasurePosition
211 | {
212 | get
213 | {
214 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
215 | return Helper.Reflection.GetField(bobberBar, KeyHelper.treasurePosition, true).GetValue();
216 | }
217 | set
218 | {
219 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
220 | Helper.Reflection.GetField(bobberBar, KeyHelper.treasurePosition, true).SetValue(value);
221 | }
222 | }
223 |
224 | private Vector2 BarTreasureShake
225 | {
226 | set
227 | {
228 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
229 | Helper.Reflection.GetField(bobberBar, KeyHelper.treasureShake, true).SetValue(value);
230 | }
231 | }
232 |
233 | private int BarWhichFish
234 | {
235 | get
236 | {
237 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
238 | return Helper.Reflection.GetField(bobberBar, KeyHelper.whichFish, true).GetValue();
239 | }
240 | set
241 | {
242 | if (bobberBar == null) throw new NullReferenceException(nameof(bobberBar));
243 | Helper.Reflection.GetField(bobberBar, KeyHelper.whichFish, true).SetValue(value);
244 | }
245 | }
246 |
247 | /// Temporarily mothod for handle treasure catch error
248 | private void HandleTreasureCatchError()
249 | {
250 | treasureCatchStep = BarTreasureCatchLevel;
251 | Vector2 shakeValue = new Vector2(Game1.random.Next(-2, 3), Game1.random.Next(-2, 3));
252 |
253 | BarTreasureCatchLevel = treasureCatchStep + 0.0135f * 2;
254 | BarTreasureShake = shakeValue;
255 |
256 | if (BarTreasureCatchLevel >= 1.0)
257 | {
258 | Game1.playSound("newArtifact");
259 | BarTreasureCaught = true;
260 | treasureCatchStep = 0;
261 | }
262 | }
263 |
264 | /// Check if treasure chest is in bobber bar or not
265 | /// True if treasure chest is ni bobber bar
266 | private bool IsTreasureInBar()
267 | {
268 | return BarTreasurePosition + 12.0 <= BarPosition - 32.0 + BarHeight && BarTreasurePosition - 16.0 >= BarPosition - 32.0;
269 | }
270 | }
271 | }
--------------------------------------------------------------------------------
/FishingAssistant/Framework/SModEntry.cs:
--------------------------------------------------------------------------------
1 | using FishingAssistant.Menu;
2 | using Microsoft.Xna.Framework;
3 | using StardewModdingAPI;
4 | using StardewModdingAPI.Events;
5 | using StardewValley;
6 | using StardewValley.Menus;
7 | using System.Collections.Generic;
8 |
9 | namespace FishingAssistant
10 | {
11 | internal partial class ModEntry : Mod
12 | {
13 | private bool modEnable;
14 | private bool hasDisableRequest;
15 | private bool hasEnableRequest;
16 | private bool isForceEnable;
17 |
18 | private int playerStandingX;
19 | private int playerStandingY;
20 | private int playerFacingDirection;
21 |
22 | private bool maxCastPower;
23 | private bool autoHook;
24 | private bool autoCatchTreasure;
25 |
26 | private bool inFishingMiniGame;
27 |
28 | private ClickableTextureComponent modEnableIcon;
29 | private ClickableTextureComponent maxCastIcon;
30 | private ClickableTextureComponent catchTreasureIcon;
31 |
32 | private int boxSize = 96;
33 | private int iconSize = 40;
34 | private int screenMargin = 8;
35 | private int spacing = 2;
36 | private int toolBarWidth = 0;
37 |
38 | public bool IsForceEnable { get => isForceEnable; set => isForceEnable = value; }
39 |
40 | public List ModDisplayPosition = new List { "Left", "Right" };
41 | public List AutomationPresets = new List { "Default", "Custom", "Disable" };
42 | public List FishInfoDisplayPosition = new List { "Top", "UpperRight", "UpperLeft", "Bottom", "LowerRight", "LowerLeft" };
43 |
44 | private void Initialize(IModHelper helper)
45 | {
46 | Config = helper.ReadConfig();
47 | I18n.Init(helper.Translation);
48 |
49 | helper.Events.GameLoop.GameLaunched += OnGameLaunched;
50 | helper.Events.GameLoop.UpdateTicked += OnUpdateTicked;
51 | helper.Events.Display.MenuChanged += OnMenuChanged;
52 | helper.Events.Display.RenderedActiveMenu += OnRenderMenu;
53 | helper.Events.Input.ButtonPressed += OnButtonPressed;
54 | helper.Events.Display.RenderingHud += OnRenderingHud;
55 | helper.Events.GameLoop.TimeChanged += OnTimeChanged;
56 | helper.Events.GameLoop.DayStarted += OnDayStarted;
57 |
58 | Monitor.Log("Initialized (press F8 to reload config)", LogLevel.Info);
59 | }
60 |
61 | private void OnEnableModButtonPressed(ButtonPressedEventArgs e)
62 | {
63 | if (e.Button == Config.EnableModButton)
64 | ToggleMod();
65 | }
66 |
67 | private void ToggleMod()
68 | {
69 | if (modEnable)
70 | {
71 | isForceEnable = false;
72 | if (modState == ModState.Fishing || modState == ModState.Loot)
73 | {
74 | hasDisableRequest = true;
75 | Game1.playSound("coin");
76 | AddHUDMessage(2, I18n.Hud_Message_Request_Disable());
77 | return;
78 | }
79 | }
80 | else
81 | {
82 | if (Game1.timeOfDay >= Config.PauseFishingTime * 100 && Config.EnableAutoPauseFishing)
83 | {
84 | if (hasEnableRequest)
85 | {
86 | hasEnableRequest = false;
87 | isForceEnable = true;
88 | }
89 | else
90 | {
91 | hasEnableRequest = true;
92 | Game1.playSound("coin");
93 | AddHUDMessage(2, I18n.Hud_Message_Force_Enable(), Config.EnableModButton.ToString());
94 | return;
95 | }
96 | }
97 | }
98 |
99 | modEnable = isForceEnable || !modEnable;
100 |
101 | if (Game1.isFestival())
102 | {
103 | string status = modEnable ? I18n.Mod_Status_Enable() : I18n.Mod_Status_Disable();
104 | AddHUDMessage(2, I18n.Hud_Message_Mod_Toggle(), status);
105 | }
106 |
107 | if (modEnable) GetPlayerData();
108 | else modState = ModState.Disable;
109 | }
110 |
111 | private void OnCastPowerButtonPressed(ButtonPressedEventArgs e)
112 | {
113 | if (e.Button == Config.CastPowerButton)
114 | {
115 | maxCastPower = !maxCastPower;
116 | if (Game1.isFestival())
117 | {
118 | string status = maxCastPower ? I18n.Mod_Status_Enable() : I18n.Mod_Status_Disable();
119 | AddHUDMessage(2, I18n.Hud_Message_Cast_Power(), status);
120 | }
121 | }
122 | }
123 |
124 | private void OnCatchTreasureButtonPressed(ButtonPressedEventArgs e)
125 | {
126 | if (e.Button == Config.CatchTreasureButton)
127 | {
128 | autoCatchTreasure = !autoCatchTreasure;
129 | if (Game1.isFestival())
130 | {
131 | string status = autoCatchTreasure ? I18n.Mod_Status_Enable() : I18n.Mod_Status_Disable();
132 | AddHUDMessage(2, I18n.Hud_Message_Catch_Treasure(), status);
133 | }
134 | }
135 | }
136 |
137 | private void OnToggleMenuButtonPressed(ButtonPressedEventArgs e)
138 | {
139 | if (e.Button == Config.OpenMenuButton && !(Game1.activeClickableMenu is FishingAssistantMenu))
140 | {
141 | Game1.activeClickableMenu = new FishingAssistantMenu(this, Config);
142 | }
143 | }
144 |
145 | private void ReloadConfig(bool hideMessage = true)
146 | {
147 | Config = Helper.ReadConfig();
148 |
149 | autoEatWhenLowEnergy = (Config.EnableAutoEatFood && Config.EnergyPrecentToEat == 0);
150 |
151 | switch (Config.FishInfoDisplayPosition)
152 | {
153 | case "Top":
154 | displayOrder = new List() { "Top", "UpperRight", "UpperLeft", "LowerRight" };
155 | break;
156 |
157 | case "UpperRight":
158 | displayOrder = new List() { "UpperRight", "UpperLeft", "LowerRight" };
159 | break;
160 |
161 | case "UpperLeft":
162 | displayOrder = new List() { "UpperLeft", "UpperRight", "LowerLeft" };
163 | break;
164 |
165 | case "Bottom":
166 | displayOrder = new List() { "Bottom", "LowerRight", "LowerLeft", "UpperRight" };
167 |
168 | break;
169 |
170 | case "LowerRight":
171 | displayOrder = new List() { "LowerRight", "LowerLeft", "UpperRight" };
172 | break;
173 |
174 | case "LowerLeft":
175 | displayOrder = new List() { "LowerLeft", "LowerRight", "UpperLeft" };
176 | break;
177 |
178 | default:
179 | displayOrder = new List() { "UpperRight", "UpperLeft", "LowerLeft" };
180 | this.Monitor.Log($"Invalid config value {Config.FishInfoDisplayPosition} for FishDisplayPosition. Valid entries include Top, Bottom, UpperRight, UpperLeft, LowerRight and LowerLeft.", LogLevel.Warn);
181 | break;
182 | }
183 |
184 | if (!hideMessage)
185 | AddHUDMessage(2, I18n.Hud_Message_Config_Saved());
186 | }
187 |
188 | public void ResetConfigurationToDefault()
189 | {
190 | Config.AutomationPresets = ModConfig.Defaults.AutomationPresets;
191 | Config.AutoAttachBait = ModConfig.Defaults.AutoAttachBait;
192 | Config.AutoAttachTackles = ModConfig.Defaults.AutoAttachTackles;
193 | Config.AutoCastFishingRod = ModConfig.Defaults.AutoCastFishingRod;
194 | Config.AutoHookFish = ModConfig.Defaults.AutoHookFish;
195 | Config.AutoPlayMiniGame = ModConfig.Defaults.AutoPlayMiniGame;
196 | Config.AutoClosePopup = ModConfig.Defaults.AutoClosePopup;
197 | Config.AutoLootTreasure = ModConfig.Defaults.AutoLootTreasure;
198 | Config.EnableAutoPauseFishing = ModConfig.Defaults.EnableAutoPauseFishing;
199 | Config.PauseFishingTime = ModConfig.Defaults.PauseFishingTime;
200 | Config.EnableAutoEatFood = ModConfig.Defaults.EnableAutoEatFood;
201 | Config.EnergyPrecentToEat = ModConfig.Defaults.EnergyPrecentToEat;
202 | Config.AllowEatingFish = ModConfig.Defaults.AllowEatingFish;
203 |
204 | Helper.WriteConfig(Config);
205 | ReloadConfig();
206 | }
207 |
208 | private void GetPlayerData()
209 | {
210 | playerStandingX = Game1.player.getStandingX();
211 | playerStandingY = Game1.player.getStandingY();
212 | playerFacingDirection = Game1.player.getDirection() != -1 ? Game1.player.getDirection() : Game1.player.FacingDirection;
213 | }
214 |
215 | private bool IsFishingMiniGameReady()
216 | {
217 | return inFishingMiniGame && bobberBar != null;
218 | }
219 |
220 | private void AddHUDMessage(int whatType, string key, params object[] args)
221 | {
222 | if (!Context.IsWorldReady) return;
223 | Game1.addHUDMessage(new HUDMessage(string.Format(key, args), whatType));
224 | }
225 |
226 | private void DrawModStatus()
227 | {
228 | if (Game1.eventUp) return;
229 |
230 | CalculateModPosition(out float toolBarTransparency, out int screenXPos, out int screenYPos, out int boxCenterY, out int boxCenterX);
231 |
232 | bool drawBox = DrawModStatusBox(toolBarTransparency, screenXPos, screenYPos, ref boxCenterX);
233 |
234 | DrawStatusIcon(toolBarTransparency, boxCenterY, boxCenterX, drawBox);
235 | }
236 |
237 | private void DrawStatusIcon(float toolBarTransparency, int boxCenterY, int boxCenterX, bool drawBox)
238 | {
239 | DrawIcon(modEnable, new Rectangle(20, 428, 10, 10),
240 | boxCenterX - (boxSize / 4) - spacing,
241 | boxCenterY - (boxSize / 4) - spacing,
242 | modEnableIcon, 2f);
243 |
244 | DrawIcon(maxCastPower, new Rectangle(545, 1921, 53, 19),
245 | boxCenterX - (boxSize / 4),
246 | boxCenterY + (boxSize / 4) - (iconSize / 2) + spacing,
247 | maxCastIcon, 1f);
248 |
249 | DrawIcon(autoCatchTreasure, new Rectangle(137, 412, 10, 11),
250 | boxCenterX + (boxSize / 4) - (iconSize / 2) + spacing,
251 | boxCenterY - (boxSize / 4) - spacing,
252 | catchTreasureIcon, 2f);
253 |
254 | void DrawIcon(bool value, Rectangle source, int x, int y, ClickableTextureComponent icon, float scale)
255 | {
256 | float iconTransparency = value ? 1 : drawBox ? 0.2f : 0;
257 | icon = new ClickableTextureComponent(new Rectangle(x, y, iconSize, iconSize), Game1.mouseCursors, source, scale);
258 | icon.draw(Game1.spriteBatch, Color.White * toolBarTransparency * iconTransparency, 0);
259 | }
260 | }
261 |
262 | private bool DrawModStatusBox(float toolBarTransparency, int screenXPos, int screenYPos, ref int boxCenterX)
263 | {
264 | bool drawBox = false;
265 |
266 | if (modEnable || maxCastPower || autoCatchTreasure)
267 | {
268 | if (Game1.activeClickableMenu != null)
269 | {
270 | IClickableMenu.drawTextureBox(Game1.spriteBatch, Game1.menuTexture, new Rectangle(0, 256, 60, 60), screenXPos - boxSize / 2, screenYPos, boxSize, boxSize, Color.White * toolBarTransparency, 1, drawShadow: false);
271 | boxCenterX = screenXPos;
272 | }
273 | else
274 | {
275 | if (Config.ModStatusDisplayPosition == "Left")
276 | {
277 | IClickableMenu.drawTextureBox(Game1.spriteBatch, Game1.menuTexture, new Rectangle(0, 256, 60, 60), screenXPos - toolBarWidth - boxSize, screenYPos, boxSize, boxSize, Color.White * toolBarTransparency, drawShadow: false);
278 | boxCenterX = screenXPos - toolBarWidth - boxSize / 2;
279 | }
280 | else if (Config.ModStatusDisplayPosition == "Right")
281 | {
282 | IClickableMenu.drawTextureBox(Game1.spriteBatch, Game1.menuTexture, new Rectangle(0, 256, 60, 60), screenXPos + toolBarWidth, screenYPos, boxSize, boxSize, Color.White * toolBarTransparency, 1, drawShadow: false);
283 | boxCenterX = screenXPos + toolBarWidth + boxSize / 2;
284 | }
285 | }
286 | drawBox = true;
287 | }
288 |
289 | return drawBox;
290 | }
291 |
292 | private void CalculateModPosition(out float toolBarTransparency, out int screenXPos, out int screenYPos, out int boxCenterY, out int boxCenterX)
293 | {
294 | bool alignTop = false;
295 | Point playerGlobalPos = Game1.player.GetBoundingBox().Center;
296 | Vector2 playerLocalVec = Game1.GlobalToLocal(globalPosition: new Vector2(playerGlobalPos.X, playerGlobalPos.Y), viewport: Game1.viewport);
297 |
298 | toolBarTransparency = 1;
299 | for (int i = 0; i < Game1.onScreenMenus.Count; i++)
300 | {
301 | if (Game1.onScreenMenus[i] is Toolbar toolBar)
302 | {
303 | toolBarTransparency = Helper.Reflection.GetField(toolBar, "transparency", true).GetValue();
304 | toolBarWidth = toolBar.width / 2;
305 | break;
306 | }
307 | }
308 |
309 | if (!Game1.options.pinToolbarToggle)
310 | alignTop = playerLocalVec.Y > (float)(Game1.viewport.Height / 2 + 64);
311 |
312 | var viewport = Game1.graphics.GraphicsDevice.Viewport;
313 | screenXPos = (int)viewport.Width / 2;
314 | if (alignTop)
315 | screenYPos = screenMargin;
316 | else
317 | screenYPos = (int)viewport.Height - screenMargin - boxSize;
318 |
319 | boxCenterY = screenYPos + boxSize / 2;
320 | boxCenterX = 0;
321 | }
322 |
323 | public int GetCurrentListValue(string currentValue, List list)
324 | {
325 | return list.FindIndex(value => currentValue == value);
326 | }
327 | }
328 | }
--------------------------------------------------------------------------------
/FishingAssistant/Component/AutoAction.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework;
2 | using StardewModdingAPI;
3 | using StardewValley;
4 | using StardewValley.Menus;
5 | using StardewValley.Objects;
6 | using StardewValley.Tools;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Linq;
10 | using Object = StardewValley.Object;
11 |
12 | namespace FishingAssistant
13 | {
14 | internal partial class ModEntry : Mod
15 | {
16 | private int defaultAutoCastDelay = 60;
17 | private int defaultAutoClosePopupDelay = 30;
18 | private int defaultAutoLootDelay = 30;
19 |
20 | private int autoCastDelay;
21 | private int autoClosePopupDelay;
22 | private int autoLootDelay;
23 |
24 | private float treasureCatchStep = 0;
25 | private bool catchingTreasure;
26 |
27 | public bool autoEatWhenLowEnergy;
28 |
29 | private enum ModState { Disable, Pause, Idle, Fishing, Loot }
30 |
31 | private ModState modState;
32 |
33 | private bool CheckCurrentPreset(bool automation)
34 | {
35 | if (Config.AutomationPresets == "Custom" && automation || Config.AutomationPresets == "Default")
36 | return true;
37 | return false;
38 | }
39 |
40 | public bool AutoEatFood(bool ignoreCondition)
41 | {
42 | if (!CheckCurrentPreset(Config.EnableAutoEatFood))
43 | return false;
44 |
45 | if (!Game1.player.isEating && RodIsNotInUse() && Config.EnableAutoEatFood && (ignoreCondition || Game1.player.Stamina <= Game1.player.MaxStamina * ((float)Config.EnergyPrecentToEat / 100)))
46 | {
47 | Object bestItem = null;
48 | foreach (Object item in Game1.player.Items.OfType