forked from aedenthorn/StardewValleyMods
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4e94b7e
commit 1a4846e
Showing
19 changed files
with
743 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<Version>1.0.0</Version> | ||
<TargetFramework>net5.0</TargetFramework> | ||
<EnableHarmony>true</EnableHarmony> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Pathoschild.Stardew.ModBuildConfig" Version="4.0.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<None Update="assets\numbers.png"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</None> | ||
<None Update="manifest.json"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</None> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
using HarmonyLib; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Reflection.Emit; | ||
|
||
namespace BetterLightningRods | ||
{ | ||
/// <summary>The mod entry point.</summary> | ||
public partial class ModEntry | ||
{ | ||
public static IEnumerable<CodeInstruction> Utility_performLightningUpdate_Transpiler(IEnumerable<CodeInstruction> instructions) | ||
{ | ||
SMonitor.Log($"Transpiling Utility.performLightningUpdate"); | ||
|
||
var codes = new List<CodeInstruction>(instructions); | ||
var newCodes = new List<CodeInstruction>(); | ||
bool rodsFound = false; | ||
bool derandomFound = false; | ||
bool shuffleFound = false; | ||
bool chanceFound = false; | ||
CodeInstruction indexCode = null; | ||
for (int i = 0; i < codes.Count; i++) | ||
{ | ||
if (!rodsFound && i < codes.Count - 2 && codes[i + 2].opcode == OpCodes.Blt && codes[i + 1].opcode == OpCodes.Ldc_I4_2 && codes[i].opcode == OpCodes.Ldloc_S) | ||
{ | ||
SMonitor.Log($"Setting number of lightning rods to check to {Config.RodsToCheck}"); | ||
codes[i + 1] = new CodeInstruction(OpCodes.Ldc_I4, Config.RodsToCheck); | ||
rodsFound = true; | ||
} | ||
else if (!chanceFound && codes[i].opcode == OpCodes.Ldc_R8 && (double)codes[i].operand == 0.125) | ||
{ | ||
SMonitor.Log($"Setting lightning chance to {Config.LightningChance}%"); | ||
codes[i].operand = (double)(Config.LightningChance / 100f); | ||
chanceFound = true; | ||
} | ||
else if (!shuffleFound && Config.UniqueCheck && i < codes.Count - 2 && codes[i + 2].opcode == OpCodes.Ble && codes[i + 1].opcode == OpCodes.Ldc_I4_0 && codes[i].opcode == OpCodes.Callvirt && codes[i - 1].opcode == OpCodes.Ldloc_3) | ||
{ | ||
SMonitor.Log($"Shuffling lightning rod list"); | ||
indexCode = new CodeInstruction(OpCodes.Ldloc_S, codes[i + 4].operand); | ||
newCodes.Add(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(ModEntry), nameof(ModEntry.ShuffleRodList)))); | ||
shuffleFound = true; | ||
} | ||
else if (!derandomFound && Config.UniqueCheck && indexCode != null && i < codes.Count - 4 && codes[i + 4].opcode == OpCodes.Callvirt && (MethodInfo)codes[i + 4].operand == AccessTools.Method(typeof(Random), nameof(Random.Next), new Type[] { typeof(int) }) && codes[i + 2].opcode == OpCodes.Ldloc_3 && codes[i + 1].opcode == OpCodes.Ldloc_0 && codes[i].opcode == OpCodes.Ldloc_3) | ||
{ | ||
SMonitor.Log($"Setting check to indexed rod"); | ||
newCodes.Add(codes[i]); | ||
newCodes.Add(codes[i]); | ||
newCodes.Add(indexCode); | ||
newCodes.Add(new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(ModEntry), nameof(ModEntry.GetLightningRod)))); | ||
i += 5; | ||
derandomFound = true; | ||
} | ||
newCodes.Add(codes[i]); | ||
} | ||
|
||
return newCodes.AsEnumerable(); | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
using StardewModdingAPI; | ||
using System; | ||
|
||
namespace BetterLightningRods | ||
{ | ||
/// <summary>The API which lets other mods add a config UI through Generic Mod Config Menu.</summary> | ||
public interface IGenericModConfigMenuApi | ||
{ | ||
/********* | ||
** Methods | ||
*********/ | ||
/**** | ||
** Must be called first | ||
****/ | ||
/// <summary>Register a mod whose config can be edited through the UI.</summary> | ||
/// <param name="mod">The mod's manifest.</param> | ||
/// <param name="reset">Reset the mod's config to its default values.</param> | ||
/// <param name="save">Save the mod's current config to the <c>config.json</c> file.</param> | ||
/// <param name="titleScreenOnly">Whether the options can only be edited from the title screen.</param> | ||
/// <remarks>Each mod can only be registered once, unless it's deleted via <see cref="Unregister"/> before calling this again.</remarks> | ||
void Register(IManifest mod, Action reset, Action save, bool titleScreenOnly = false); | ||
|
||
/// <summary>Add a section title at the current position in the form.</summary> | ||
/// <param name="mod">The mod's manifest.</param> | ||
/// <param name="text">The title text shown in the form.</param> | ||
/// <param name="tooltip">The tooltip text shown when the cursor hovers on the title, or <c>null</c> to disable the tooltip.</param> | ||
void AddSectionTitle(IManifest mod, Func<string> text, Func<string> tooltip = null); | ||
|
||
/// <summary>Add a key binding at the current position in the form.</summary> | ||
/// <param name="mod">The mod's manifest.</param> | ||
/// <param name="getValue">Get the current value from the mod config.</param> | ||
/// <param name="setValue">Set a new value in the mod config.</param> | ||
/// <param name="name">The label text to show in the form.</param> | ||
/// <param name="tooltip">The tooltip text shown when the cursor hovers on the field, or <c>null</c> to disable the tooltip.</param> | ||
/// <param name="fieldId">The unique field ID for use with <see cref="OnFieldChanged"/>, or <c>null</c> to auto-generate a randomized ID.</param> | ||
void AddKeybind(IManifest mod, Func<SButton> getValue, Action<SButton> setValue, Func<string> name, Func<string> tooltip = null, string fieldId = null); | ||
|
||
/// <summary>Add a boolean option at the current position in the form.</summary> | ||
/// <param name="mod">The mod's manifest.</param> | ||
/// <param name="getValue">Get the current value from the mod config.</param> | ||
/// <param name="setValue">Set a new value in the mod config.</param> | ||
/// <param name="name">The label text to show in the form.</param> | ||
/// <param name="tooltip">The tooltip text shown when the cursor hovers on the field, or <c>null</c> to disable the tooltip.</param> | ||
/// <param name="fieldId">The unique field ID for use with <see cref="OnFieldChanged"/>, or <c>null</c> to auto-generate a randomized ID.</param> | ||
void AddBoolOption(IManifest mod, Func<bool> getValue, Action<bool> setValue, Func<string> name, Func<string> tooltip = null, string fieldId = null); | ||
|
||
|
||
/// <summary>Add an integer option at the current position in the form.</summary> | ||
/// <param name="mod">The mod's manifest.</param> | ||
/// <param name="getValue">Get the current value from the mod config.</param> | ||
/// <param name="setValue">Set a new value in the mod config.</param> | ||
/// <param name="name">The label text to show in the form.</param> | ||
/// <param name="tooltip">The tooltip text shown when the cursor hovers on the field, or <c>null</c> to disable the tooltip.</param> | ||
/// <param name="min">The minimum allowed value, or <c>null</c> to allow any.</param> | ||
/// <param name="max">The maximum allowed value, or <c>null</c> to allow any.</param> | ||
/// <param name="interval">The interval of values that can be selected.</param> | ||
/// <param name="fieldId">The unique field ID for use with <see cref="OnFieldChanged"/>, or <c>null</c> to auto-generate a randomized ID.</param> | ||
void AddNumberOption(IManifest mod, Func<int> getValue, Action<int> setValue, Func<string> name, Func<string> tooltip = null, int? min = null, int? max = null, int? interval = null, string fieldId = null); | ||
|
||
/// <summary>Add a string option at the current position in the form.</summary> | ||
/// <param name="mod">The mod's manifest.</param> | ||
/// <param name="getValue">Get the current value from the mod config.</param> | ||
/// <param name="setValue">Set a new value in the mod config.</param> | ||
/// <param name="name">The label text to show in the form.</param> | ||
/// <param name="tooltip">The tooltip text shown when the cursor hovers on the field, or <c>null</c> to disable the tooltip.</param> | ||
/// <param name="allowedValues">The values that can be selected, or <c>null</c> to allow any.</param> | ||
/// <param name="formatAllowedValue">Get the display text to show for a value from <paramref name="allowedValues"/>, or <c>null</c> to show the values as-is.</param> | ||
/// <param name="fieldId">The unique field ID for use with <see cref="OnFieldChanged"/>, or <c>null</c> to auto-generate a randomized ID.</param> | ||
void AddTextOption(IManifest mod, Func<string> getValue, Action<string> setValue, Func<string> name, Func<string> tooltip = null, string[] allowedValues = null, Func<string, string> formatAllowedValue = null, string fieldId = null); | ||
|
||
/// <summary>Remove a mod from the config UI and delete all its options and pages.</summary> | ||
/// <param name="mod">The mod's manifest.</param> | ||
void Unregister(IManifest mod); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
| ||
using StardewModdingAPI; | ||
|
||
namespace BetterLightningRods | ||
{ | ||
public class ModConfig | ||
{ | ||
public bool EnableMod { get; set; } = true; | ||
public bool UniqueCheck { get; set; } = true; | ||
public bool OnlyCheckEmpty { get; set; } = false; | ||
public int RodsToCheck { get; set; } = 2; | ||
public float LightningChance { get; set; } = 13f; | ||
public SButton LightningButton { get; set; } = SButton.F15; | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
using HarmonyLib; | ||
using Microsoft.Xna.Framework; | ||
using StardewModdingAPI; | ||
using StardewValley; | ||
using StardewValley.Characters; | ||
using StardewValley.Objects; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace BetterLightningRods | ||
{ | ||
/// <summary>The mod entry point.</summary> | ||
public partial class ModEntry : Mod | ||
{ | ||
|
||
public static IMonitor SMonitor; | ||
public static IModHelper SHelper; | ||
public static ModConfig Config; | ||
|
||
public static ModEntry context; | ||
|
||
/// <summary>The mod entry point, called after the mod is first loaded.</summary> | ||
/// <param name="helper">Provides simplified APIs for writing mods.</param> | ||
public override void Entry(IModHelper helper) | ||
{ | ||
Config = Helper.ReadConfig<ModConfig>(); | ||
|
||
if (!Config.EnableMod) | ||
return; | ||
|
||
context = this; | ||
|
||
SMonitor = Monitor; | ||
SHelper = helper; | ||
helper.Events.GameLoop.GameLaunched += GameLoop_GameLaunched; | ||
helper.Events.Input.ButtonPressed += Input_ButtonPressed; | ||
|
||
|
||
var harmony = new Harmony(ModManifest.UniqueID); | ||
|
||
harmony.Patch( | ||
original: AccessTools.Method(typeof(Utility), nameof(Utility.performLightningUpdate)), | ||
transpiler: new HarmonyMethod(typeof(ModEntry), nameof(ModEntry.Utility_performLightningUpdate_Transpiler)) | ||
); | ||
|
||
} | ||
|
||
private void Input_ButtonPressed(object sender, StardewModdingAPI.Events.ButtonPressedEventArgs e) | ||
{ | ||
if(e.Button == Config.LightningButton) | ||
{ | ||
Monitor.Log("Lightning strike!"); | ||
Utility.performLightningUpdate(Game1.timeOfDay); | ||
|
||
} | ||
} | ||
|
||
private void GameLoop_GameLaunched(object sender, StardewModdingAPI.Events.GameLaunchedEventArgs e) | ||
{ | ||
// get Generic Mod Config Menu's API (if it's installed) | ||
var configMenu = Helper.ModRegistry.GetApi<IGenericModConfigMenuApi>("spacechase0.GenericModConfigMenu"); | ||
if (configMenu is null) | ||
return; | ||
|
||
// register mod | ||
configMenu.Register( | ||
mod: ModManifest, | ||
reset: () => Config = new ModConfig(), | ||
save: () => Helper.WriteConfig(Config) | ||
); | ||
|
||
configMenu.AddBoolOption( | ||
mod: ModManifest, | ||
name: () => "Mod Enabled?", | ||
getValue: () => Config.EnableMod, | ||
setValue: value => Config.EnableMod = value | ||
); | ||
configMenu.AddBoolOption( | ||
mod: ModManifest, | ||
name: () => "Unique Check?", | ||
tooltip: () => "Don't check the same rod twice per strike.", | ||
getValue: () => Config.UniqueCheck, | ||
setValue: value => Config.UniqueCheck = value | ||
); | ||
configMenu.AddNumberOption( | ||
mod: ModManifest, | ||
name: () => "Rods To Check", | ||
tooltip: () => "Each time lightning strikes, check this many rods to see if they can receive the charge.", | ||
getValue: () => Config.RodsToCheck, | ||
setValue: value => Config.RodsToCheck = value | ||
); | ||
configMenu.AddNumberOption( | ||
mod: ModManifest, | ||
name: () => "Base Lightning Chance", | ||
getValue: () => (int)Config.LightningChance, | ||
setValue: value => Config.LightningChance = value, | ||
min: 0, | ||
max: 100 | ||
); | ||
} | ||
private static int GetLightningRod(List<Vector2> rods, int index) | ||
{ | ||
int rod = Math.Min(index, rods.Count - 1); | ||
return rod; | ||
} | ||
private static List<Vector2> ShuffleRodList(List<Vector2> rods) | ||
{ | ||
//SMonitor.Log($"Shuffling {rods.Count} rods"); | ||
ShuffleList(rods); | ||
if (Config.OnlyCheckEmpty) | ||
{ | ||
for(int i = rods.Count - 1; i >= 0; i--) | ||
{ | ||
if (Game1.getFarm().objects[rods[i]].heldObject.Value != null) | ||
rods.RemoveAt(i); | ||
} | ||
} | ||
return rods; | ||
} | ||
public static List<T> ShuffleList<T>(List<T> list) | ||
{ | ||
int n = list.Count; | ||
while (n > 1) | ||
{ | ||
n--; | ||
int k = Game1.random.Next(n + 1); | ||
var value = list[k]; | ||
list[k] = list[n]; | ||
list[n] = value; | ||
} | ||
return list; | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"Name": "Better Lightning Rods", | ||
"Author": "aedenthorn", | ||
"Version": "0.1.0", | ||
"Description": "Better Lightning Rods.", | ||
"UniqueID": "aedenthorn.BetterLightningRods", | ||
"EntryDll": "BetterLightningRods.dll", | ||
"MinimumApiVersion": "3.13.0", | ||
"ModUpdater": { | ||
"Repository": "StardewValleyMods", | ||
"User": "aedenthorn", | ||
"Directory": "_releases", | ||
"ModFolder": "BetterLightningRods" | ||
}, | ||
"UpdateKeys": [ "Nexus:10631" ], | ||
"Dependencies": [ | ||
{ | ||
"UniqueID": "Platonymous.ModUpdater", | ||
"IsRequired": false | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using StardewValley; | ||
using StardewValley.Characters; | ||
|
||
namespace PetBed | ||
{ | ||
/// <summary>The mod entry point.</summary> | ||
public partial class ModEntry | ||
{ | ||
|
||
private static bool Pet_warpToFarmHouse_Prefix(Pet __instance, Farmer who, ref int ____currentBehavior) | ||
{ | ||
SMonitor.Log("Warping pet to farmhouse"); | ||
return !Config.EnableMod || Game1.random.NextDouble() > Config.BedChance / 100f || !WarpPetToBed(__instance, Utility.getHomeOfFarmer(who), ref ____currentBehavior, false); | ||
} | ||
|
||
private static bool Pet_setAtFarmPosition_Prefix(Pet __instance, ref int ____currentBehavior) | ||
{ | ||
SMonitor.Log("Setting pet to farm position"); | ||
return !Config.EnableMod || Game1.random.NextDouble() > Config.BedChance / 100f || !Game1.IsMasterGame || Game1.isRaining || !WarpPetToBed(__instance, Game1.getFarm(), ref ____currentBehavior, true); | ||
} | ||
private static void Pet_dayUpdate_Prefix(Pet __instance, ref bool __state) | ||
{ | ||
if(Config.EnableMod && __instance.currentLocation is Farm && !Game1.isRaining && Game1.random.NextDouble() < Config.BedChance / 100f && Game1.IsMasterGame) | ||
{ | ||
__state = true; | ||
} | ||
} | ||
private static void Pet_dayUpdate_Postfix(Pet __instance, bool __state, ref int ____currentBehavior) | ||
{ | ||
if(__state) | ||
{ | ||
SMonitor.Log("Setting pet to farm position"); | ||
WarpPetToBed(__instance, Game1.getFarm(), ref ____currentBehavior, true); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.