diff --git a/ArrowMod.csproj b/ArrowMod.csproj
index d8cfe1b..cc92441 100644
--- a/ArrowMod.csproj
+++ b/ArrowMod.csproj
@@ -1,91 +1,47 @@
-
-
-
+
+
+
+
+
+ net6.0
+
+
+ Latest
+
+
+ enable
+
+
+ enable
+
+
+ false
+
+
+
+
+
+ embedded
+
- Debug
- AnyCPU
- {DAF59C7B-B568-4A66-BECA-0D8B47971845}
- Library
- Properties
- ArrowMod
- ArrowMod
- v4.7.2
- 512
-
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
- false
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
- false
+ OnBuildSuccess
+
+
+
-
- False
- ..\..\..\..\Games\SteamLibrary\steamapps\common\TheLongDark\MelonLoader\0Harmony.dll
-
-
- ..\..\..\..\SteamLibrary\steamapps\common\TheLongDark\tld_Data\Managed\Assembly-CSharp.dll
- False
-
-
- False
- ..\..\..\..\Games\SteamLibrary\steamapps\common\TheLongDark\MelonLoader\Managed\Il2Cppmscorlib.dll
-
-
-
- False
- ..\..\..\..\Games\SteamLibrary\steamapps\common\TheLongDark\MelonLoader\MelonLoader.dll
-
-
- False
- False
-
-
-
- False
- ..\..\..\..\Games\SteamLibrary\steamapps\common\TheLongDark\MelonLoader\Managed\UnhollowerBaseLib.dll
-
-
- False
- ..\..\..\..\Games\SteamLibrary\steamapps\common\TheLongDark\MelonLoader\Managed\UnhollowerRuntimeLib.dll
-
-
- ..\..\..\..\SteamLibrary\steamapps\common\TheLongDark\tld_Data\Managed\UnityEngine.dll
- False
-
-
- ..\..\..\..\SteamLibrary\steamapps\common\TheLongDark\tld_Data\Managed\UnityEngine.CoreModule.dll
- False
-
-
-
-
-
-
-
+
+
-
-
+
+ ..\..\..\..\Games\SteamLibrary\steamapps\common\TheLongDark\Mods\ModSettings.dll
+
-
-
- xcopy /y "$(ProjectDir)bin\Debug\ArrowMod.dll" "D:\Games\SteamLibrary\steamapps\common\TheLongDark\Mods\"
-
+
+
+
+
-
\ No newline at end of file
+
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
index a1262a3..2174ee7 100644
--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -1,20 +1,14 @@
using MelonLoader;
using System.Reflection;
-using System.Runtime.InteropServices;
-using BuildInfo = ArrowMod.BuildInfo;
-[assembly: ComVisible(false)]
-[assembly: Guid("daf59c7b-b568-4a66-beca-0d8b47971845")]
+//This is a C# comment. Comments have no impact on compilation.
-[assembly: AssemblyTitle(BuildInfo.Name)]
-[assembly: AssemblyDescription(BuildInfo.Description)]
-[assembly: AssemblyCompany(BuildInfo.Company)]
-[assembly: AssemblyProduct(BuildInfo.Name)]
-[assembly: AssemblyCopyright("Created by " + BuildInfo.Author)]
-[assembly: AssemblyTrademark(BuildInfo.Company)]
-[assembly: AssemblyCulture("")]
+[assembly: AssemblyTitle(ArrowMod.BuildInfo.ModName)]
+[assembly: AssemblyCopyright($"Created by {ArrowMod.BuildInfo.ModAuthor}")]
-[assembly: AssemblyVersion(BuildInfo.Version)]
-[assembly: AssemblyFileVersion(BuildInfo.Version)]
-[assembly: MelonInfo(typeof(ArrowMod.ArrowMod), BuildInfo.Name, BuildInfo.Version, BuildInfo.Author, BuildInfo.DownloadLink)]
+[assembly: AssemblyVersion(ArrowMod.BuildInfo.ModVersion)]
+[assembly: AssemblyFileVersion(ArrowMod.BuildInfo.ModVersion)]
+[assembly: MelonInfo(typeof(ArrowMod.ArrowMod), ArrowMod.BuildInfo.ModName, ArrowMod.BuildInfo.ModVersion, ArrowMod.BuildInfo.ModAuthor)]
+
+//This tells MelonLoader that the mod is only for The Long Dark.
[assembly: MelonGame("Hinterland", "TheLongDark")]
\ No newline at end of file
diff --git a/README.md b/README.md
index b082d71..3b0d36b 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,8 @@ This mod for *The Long Dark* allows you to adjust how arrows are crafted. Requir
## Installation
+Always up to date instructions: https://xpazeman.com/tld-mod-list/install.html
+
1. If you haven't done so already, install MelonLoader by downloading and running [MelonLoader.Installer.exe](https://github.com/HerpDerpinstine/MelonLoader/releases/latest/download/MelonLoader.Installer.exe)
2. Download the latest version of `ArrowMod.dll` from the [releases page](https://github.com/ds5678/tld-ArrowMod/releases/latest)
3. Download the latest version of `ModSettings.dll` from its [release page](https://github.com/zeobviouslyfakeacc/ModSettings/releases/latest)
@@ -19,4 +21,6 @@ This mod for *The Long Dark* allows you to adjust how arrows are crafted. Requir
## Notes
+Settings change will require game restart.
+
Many thanks to all TLD moding commniunity for support and assist.
diff --git a/src/ArrowMod.cs b/src/ArrowMod.cs
index fb56a2e..fac33cd 100644
--- a/src/ArrowMod.cs
+++ b/src/ArrowMod.cs
@@ -1,24 +1,25 @@
using MelonLoader;
-using UnityEngine;
namespace ArrowMod
{
- public static class BuildInfo
- {
- public const string Name = "ArrowMod"; // Name of the Mod. (MUST BE SET)
- public const string Description = "A mod to make arrow crafting more realistic."; // Description for the Mod. (Set as null if none)
- public const string Author = "ttr, ds5678"; // Author of the Mod. (MUST BE SET)
- public const string Company = null; // Company that made the Mod. (Set as null if none)
- public const string Version = "1.7.1"; // Version of the Mod. (MUST BE SET)
- public const string DownloadLink = null; // Download Link for the Mod. (Set as null if none)
- }
- internal class ArrowMod : MelonMod
- {
- public override void OnApplicationStart()
- {
- Debug.Log($"[{Info.Name}] Version {Info.Version} loaded!");
- Settings.OnLoad();
- }
- }
+ public static class BuildInfo
+ {
+ internal const string ModName = "ArrowMod";
+ internal const string ModAuthor = "ttr";
+ internal const string ModVersion = "1.8.0";
+ }
+ internal class ArrowMod : MelonMod
+ {
+
+ public override void OnInitializeMelon()
+ {
+ Settings.OnLoad();
+ LoggerInstance.Msg($"[{BuildInfo.ModName}] Version {BuildInfo.ModVersion} loaded!");
+ }
+ public static void Log(string msg)
+ {
+ MelonLogger.Msg(msg);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Patches.cs b/src/Patches.cs
index 5401670..2cdfdb8 100644
--- a/src/Patches.cs
+++ b/src/Patches.cs
@@ -1,22 +1,29 @@
using MelonLoader;
-using UnhollowerBaseLib;
using HarmonyLib;
using UnityEngine;
-
+using Il2Cpp;
+using Il2CppInterop.Runtime.InteropTypes.Arrays;
+using Il2CppTLD.Gear;
+using UnityEngine.Playables;
+using Il2CppSystem.Linq.Expressions;
namespace ArrowMod
{
internal static class Patches
{
- [HarmonyPatch(typeof(GameManager), "Awake")]
- public class GameManager_Awake
+
+ //[HarmonyPatch(typeof(GameManager), "Awake")]
+ [HarmonyPatch(typeof(Panel_Crafting), nameof(Panel_Crafting.Initialize))]
+ public class InterfaceManager_Awake
{
private static void Postfix()
{
-
+
+ ArrowMod.Log("Adding blueprints.");
if (Settings.options.arrowUseLine)
{
- BlueprintItem bpi = GameManager.GetBlueprints().AddComponent();
+ BlueprintData bpi = new();
+
// Inputs
bpi.m_KeroseneLitersRequired = 0f;
bpi.m_GunpowderKGRequired = 0f;
@@ -34,27 +41,24 @@ private static void Postfix()
bpi.m_RequiresLitFire = false;
bpi.m_RequiredCraftingLocation = CraftingLocation.Workbench;
bpi.m_DurationMinutes = Settings.options.arrowCraftTime; // whaever, we need to set this in ItemPassFilter
- bpi.m_CraftingAudio = "PLAY_CRAFTINGARROWS";
+ bpi.m_CraftingAudio = MakeAudioEvent("PLAY_CRAFTINGARROWS");
+
bpi.m_AppliedSkill = SkillType.None;
bpi.m_ImprovedSkill = SkillType.None;
- bpi.m_RequiredGear = new Il2CppReferenceArray(4)
- {
- [0] = GetGearItemPrefab("GEAR_Line"),
- [1] = GetGearItemPrefab("GEAR_CrowFeather"),
- [2] = GetGearItemPrefab("GEAR_ArrowShaft"),
- [3] = GetGearItemPrefab("GEAR_ArrowHead")
- };
- bpi.m_RequiredGearUnits = new Il2CppStructArray(4)
+ bpi.m_RequiredGear = new Il2CppReferenceArray(0) { };
+
+ bpi.m_RequiredGear = new Il2CppReferenceArray(4)
{
- [0] = 1,
- [1] = 3,
- [2] = 1,
- [3] = 1
+ [0] = new BlueprintData.RequiredGearItem() { m_Count = 1, m_Item = GetGearItemPrefab("GEAR_Line") },
+ [1] = new BlueprintData.RequiredGearItem() { m_Count = 3, m_Item = GetGearItemPrefab("GEAR_CrowFeather") },
+ [2] = new BlueprintData.RequiredGearItem() { m_Count = 1, m_Item = GetGearItemPrefab("GEAR_ArrowShaft") },
+ [3] = new BlueprintData.RequiredGearItem() { m_Count = 1, m_Item = GetGearItemPrefab("GEAR_ArrowHead") }
};
+ InterfaceManager.GetInstance().m_BlueprintManager.m_AllBlueprints.Add(bpi);
if (Settings.options.craftFletchingFromBark)
{
- BlueprintItem bpi2 = GameManager.GetBlueprints().AddComponent();
+ BlueprintData bpi2 = new();
// Inputs
bpi2.m_KeroseneLitersRequired = 0f;
bpi2.m_GunpowderKGRequired = 0f;
@@ -72,28 +76,22 @@ private static void Postfix()
bpi2.m_RequiresLitFire = false;
bpi2.m_RequiredCraftingLocation = CraftingLocation.Workbench;
bpi2.m_DurationMinutes = 2 * (Settings.options.arrowCraftTime + Settings.options.craftFletchingFromBarkTime); // whaever, we need to set this in ItemPassFilter
- bpi2.m_CraftingAudio = "PLAY_CRAFTINGARROWS";
+ bpi2.m_CraftingAudio = MakeAudioEvent("PLAY_CRAFTINGARROWS");
bpi2.m_AppliedSkill = SkillType.None;
bpi2.m_ImprovedSkill = SkillType.None;
- bpi2.m_RequiredGear = new Il2CppReferenceArray(4)
- {
- [0] = GetGearItemPrefab("GEAR_Line"),
- [1] = GetGearItemPrefab("GEAR_BarkTinder"),
- [2] = GetGearItemPrefab("GEAR_ArrowShaft"),
- [3] = GetGearItemPrefab("GEAR_ArrowHead")
- };
- bpi2.m_RequiredGearUnits = new Il2CppStructArray(4)
+ bpi2.m_RequiredGear = new Il2CppReferenceArray(4)
{
- [0] = 1,
- [1] = 1,
- [2] = 1,
- [3] = 1
+ [0] = new BlueprintData.RequiredGearItem() { m_Count = 1, m_Item = GetGearItemPrefab("GEAR_Line") },
+ [1] = new BlueprintData.RequiredGearItem() { m_Count = 1, m_Item = GetGearItemPrefab("GEAR_BarkTinder") },
+ [2] = new BlueprintData.RequiredGearItem() { m_Count = 1, m_Item = GetGearItemPrefab("GEAR_ArrowShaft") },
+ [3] = new BlueprintData.RequiredGearItem() { m_Count = 1, m_Item = GetGearItemPrefab("GEAR_ArrowHead") }
};
+ InterfaceManager.GetInstance().m_BlueprintManager.m_AllBlueprints.Add(bpi2);
}
}
if (Settings.options.craftArrowFromWood)
{
- BlueprintItem bpi3 = GameManager.GetBlueprints().AddComponent();
+ BlueprintData bpi3 = new();
// Inputs
bpi3.m_KeroseneLitersRequired = 0f;
bpi3.m_GunpowderKGRequired = 0f;
@@ -111,17 +109,15 @@ private static void Postfix()
bpi3.m_RequiresLitFire = false;
bpi3.m_RequiredCraftingLocation = CraftingLocation.Workbench;
bpi3.m_DurationMinutes = 180; // with knife it will be 1/2 of this time; it will be much longer than from branch but it takes time to cut arrow from plank
- bpi3.m_CraftingAudio = "PLAY_CRAFTINGARROWS";
+ bpi3.m_CraftingAudio = MakeAudioEvent("PLAY_CRAFTINGARROWS");
bpi3.m_AppliedSkill = SkillType.None;
bpi3.m_ImprovedSkill = SkillType.None;
- bpi3.m_RequiredGear = new Il2CppReferenceArray(1)
- {
- [0] = GetGearItemPrefab("GEAR_Hardwood")
- };
- bpi3.m_RequiredGearUnits = new Il2CppStructArray(1)
+ bpi3.m_RequiredGear = new Il2CppReferenceArray(1)
{
- [0] = 1
+ [0] = new BlueprintData.RequiredGearItem() { m_Count = 1, m_Item = GetGearItemPrefab("GEAR_Hardwood") }
};
+ InterfaceManager.GetInstance().m_BlueprintManager.m_AllBlueprints.Add(bpi3);
+ InterfaceManager.GetInstance().m_BlueprintManager.m_AllBlueprints.Sort();
}
}
}
@@ -129,7 +125,7 @@ private static void Postfix()
[HarmonyPatch(typeof(Panel_Crafting), "ItemPassesFilter")]
private static class Panel_Crafting_ItemPassesFilter
{
- private static void Postfix(Panel_Crafting __instance, ref bool __result, BlueprintItem bpi)
+ private static void Postfix(Panel_Crafting __instance, ref bool __result, BlueprintData bpi)
{
if (bpi?.m_CraftedResult?.name == "GEAR_Arrow")
{
@@ -137,7 +133,7 @@ private static void Postfix(Panel_Crafting __instance, ref bool __result, Bluepr
{
__result = false;
}
- if (bpi.m_RequiredGear[1] == GetGearItemPrefab("GEAR_BarkTinder"))
+ if (bpi.m_RequiredGear[1].m_Item == GetGearItemPrefab("GEAR_BarkTinder"))
{
bpi.m_DurationMinutes = (Settings.options.arrowCraftTime + Settings.options.craftFletchingFromBarkTime) * 2;
}
@@ -156,7 +152,6 @@ private static void Postfix(Panel_Crafting __instance, ref bool __result, Bluepr
}
}
-
// based on better mending mod
[HarmonyPatch(typeof(Panel_Crafting), "RefreshSelectedBlueprint")]
public class Panel_Crafting_RefreshSelectedBlueprint
@@ -164,10 +159,11 @@ public class Panel_Crafting_RefreshSelectedBlueprint
private static void Postfix(Panel_Crafting __instance)
{
//__instance.m_SelectedDescription.color = whiteColor;
- BlueprintItem bpi = __instance.m_SelectedBPI;
+ BlueprintData bpi = __instance.m_SelectedBPI;
if (bpi)
{
- if (bpi.m_CraftedResult == GetGearItemPrefab("GEAR_ArrowShaft") && bpi.m_RequiredGear[0] == GetGearItemPrefab("GEAR_Hardwood"))
+ __instance.m_SelectedDescription.color = whiteColor;
+ if (bpi.m_CraftedResult == GetGearItemPrefab("GEAR_ArrowShaft") && bpi.m_RequiredGear[0].m_Item == GetGearItemPrefab("GEAR_Hardwood"))
{
int currentArcherySkill = GameManager.GetSkillArchery().GetCurrentTierNumber() + 1;
int requiredArcherySkill = Settings.options.craftArrowFromWoodLevel;
@@ -177,7 +173,7 @@ private static void Postfix(Panel_Crafting __instance)
__instance.m_SelectedDescription.color = redColor;
}
}
- if (bpi.m_CraftedResult == GetGearItemPrefab("GEAR_Arrow") && bpi.m_RequiredGear[1] == GetGearItemPrefab("GEAR_BarkTinder"))
+ if (bpi.m_CraftedResult == GetGearItemPrefab("GEAR_Arrow") && bpi.m_RequiredGear[1].m_Item == GetGearItemPrefab("GEAR_BarkTinder"))
{
int currentArcherySkill = GameManager.GetSkillArchery().GetCurrentTierNumber() + 1;
int requiredArcherySkill = Settings.options.craftFletchingFromBarkLevel;
@@ -192,13 +188,13 @@ private static void Postfix(Panel_Crafting __instance)
}
// based on better mending mod
- [HarmonyPatch(typeof(BlueprintItem), "CanCraftBlueprint")]
- private class BlueprintItem_CanCraftBlueprint
+ [HarmonyPatch(typeof(BlueprintData), "CanCraftBlueprint")]
+ private class BlueprintData_CanCraftBlueprint
{
- private static void Postfix(ref bool __result, BlueprintItem __instance)
+ private static void Postfix(ref bool __result, BlueprintData __instance)
{
- if (__instance.m_CraftedResult == GetGearItemPrefab("GEAR_ArrowShaft") && __instance.m_RequiredGear[0] == GetGearItemPrefab("GEAR_Hardwood") && __result)
+ if (__instance.m_CraftedResult == GetGearItemPrefab("GEAR_ArrowShaft") && __instance.m_RequiredGear[0].m_Item == GetGearItemPrefab("GEAR_Hardwood") && __result)
{
int currentArcherySkill = GameManager.GetSkillArchery().GetCurrentTierNumber() + 1;
int requiredArcherySkill = Settings.options.craftArrowFromWoodLevel;
@@ -207,7 +203,7 @@ private static void Postfix(ref bool __result, BlueprintItem __instance)
__result = false;
}
}
- if (__instance.m_CraftedResult == GetGearItemPrefab("GEAR_Arrow") && __instance.m_RequiredGear[1] == GetGearItemPrefab("GEAR_BarkTinder") && __result)
+ if (__instance.m_CraftedResult == GetGearItemPrefab("GEAR_Arrow") && __instance.m_RequiredGear[1].m_Item == GetGearItemPrefab("GEAR_BarkTinder") && __result)
{
int currentArcherySkill = GameManager.GetSkillArchery().GetCurrentTierNumber() + 1;
int requiredArcherySkill = Settings.options.craftFletchingFromBarkLevel;
@@ -219,8 +215,35 @@ private static void Postfix(ref bool __result, BlueprintItem __instance)
}
}
- private static GearItem GetGearItemPrefab(string name) => Resources.Load(name).Cast().GetComponent();
- private static ToolsItem GetToolItemPrefab(string name) => Resources.Load(name).Cast().GetComponent();
+ //private static GearItem GetGearItemPrefab(string name) => Resources.Load(name).Cast().GetComponent();
+ private static GearItem GetGearItemPrefab(string name)
+ {
+ return GearItem.LoadGearItemPrefab(name);
+ }
+ //private static ToolsItem GetToolItemPrefab(string name) => Resources.Load(name).Cast().GetComponent();
+ private static ToolsItem GetToolItemPrefab(string name)
+ {
+ return GearItem.LoadGearItemPrefab(name).m_ToolsItem;
+ }
+ // from CraftingRevisions by ds5678 and STBlade
+ public static Il2CppAK.Wwise.Event? MakeAudioEvent(string eventName)
+ {
+ if (eventName == null)
+ {
+ return null;
+ }
+ uint eventId = AkSoundEngine.GetIDFromString(eventName);
+ if (eventId <= 0 || eventId >= 4294967295)
+ {
+ return null;
+ }
+
+ Il2CppAK.Wwise.Event newEvent = new();
+ newEvent.WwiseObjectReference = new WwiseEventReference();
+ newEvent.WwiseObjectReference.objectName = eventName;
+ newEvent.WwiseObjectReference.id = eventId;
+ return newEvent;
+ }
private static readonly Color whiteColor = new Color(0.7f, 0.7f, 0.7f);
private static readonly Color redColor = new Color(0.7f, 0f, 0f);
diff --git a/src/Settings.cs b/src/Settings.cs
index b6adb23..f530b4a 100644
--- a/src/Settings.cs
+++ b/src/Settings.cs
@@ -2,9 +2,13 @@
namespace ArrowMod
{
+
internal class ArrowModSettings : JsonModSettings
{
- [Name("Arrowhead craft time")]
+ [Section("Arrow Mod Settings")]
+
+
+ [Name("Arrowhead craft time")]
[Description("Minutes to craft 2 arrowheads. Default is 60, recommended is 20-40")]
[Slider(1, 120)]
public int arrowHeadCraftTime = 60;
@@ -15,7 +19,7 @@ internal class ArrowModSettings : JsonModSettings
public int arrowCraftTime = 90;
[Name("Use line")]
- [Description("Require 1 line to craft an arrow. Note: Due to game limitation, only 3 first ingredients are disaied in crafing menu - eneblaing this will require 4, so arrow head, even if not disaplyed, still is needed.")]
+ [Description("Require 1 line to craft an arrow.\nNote: Due to game limitation, only 3 first ingredients are disaied in crafing menu - eneblaing this will require 4, so arrow head, even if not disaplyed, still is needed.")]
public bool arrowUseLine = false;
[Name("Craft Arrowshaft from Hardwood")]
@@ -28,7 +32,7 @@ internal class ArrowModSettings : JsonModSettings
public int craftArrowFromWoodLevel = 5;
[Name("Craft arrow fletchings from Bark")]
- [Description("Allow to use birch bark to craft arrow fletchings. NOTE: Require 'Use line' to be turn on. NOTE2: resulting arrow is same as vanilla one, meaning deconstricting it will yeld feathers.")]
+ [Description("Allow to use birch bark to craft arrow fletchings.\nNOTE: Require 'Use line' to be turn on.\nNOTE2: resulting arrow is same as vanilla one, meaning deconstricting it will yeld feathers.")]
public bool craftFletchingFromBark = false;
[Name("... skill level")]
@@ -41,7 +45,10 @@ internal class ArrowModSettings : JsonModSettings
[Slider(0, 20)]
public int craftFletchingFromBarkTime = 5;
- }
+
+
+
+ }
internal static class Settings
{
public static ArrowModSettings options;