using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Pathfinder")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Crystal")]
[assembly: AssemblyProduct("Pathfinder")]
[assembly: AssemblyCopyright("Copyright © 2023 Crystal Ferrai")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("deb680b1-786f-4e93-8793-25e19b570fef")]
[assembly: AssemblyFileVersion("2.0.13.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("2.0.13.0")]
namespace Pathfinder;
[BepInPlugin("dev.crystal.pathfinder", "Pathfinder", "2.0.13.0")]
[BepInProcess("valheim.exe")]
[BepInProcess("valheim_server.exe")]
public class PathfinderPlugin : BaseUnityPlugin
{
[HarmonyPatch(typeof(Minimap))]
private static class Minimap_Patches
{
private enum TranspilerState
{
Searching,
Checking,
Finishing
}
[CompilerGenerated]
private sealed class <UpdateExplore_Transpiler>d__1 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IDisposable, IEnumerator
{
private int <>1__state;
private CodeInstruction <>2__current;
private int <>l__initialThreadId;
private IEnumerable<CodeInstruction> instructions;
public IEnumerable<CodeInstruction> <>3__instructions;
private TranspilerState <state>5__2;
private CodeInstruction <previous>5__3;
private IEnumerator<CodeInstruction> <>7__wrap3;
private CodeInstruction <instruction>5__5;
CodeInstruction IEnumerator<CodeInstruction>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <UpdateExplore_Transpiler>d__1(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if (num == -3 || (uint)(num - 1) <= 5u)
{
try
{
}
finally
{
<>m__Finally1();
}
}
<previous>5__3 = null;
<>7__wrap3 = null;
<instruction>5__5 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0166: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Expected O, but got Unknown
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_0134: Expected O, but got Unknown
try
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<state>5__2 = TranspilerState.Searching;
<previous>5__3 = null;
<>7__wrap3 = instructions.GetEnumerator();
<>1__state = -3;
goto IL_0206;
case 1:
<>1__state = -3;
goto IL_01ff;
case 2:
<>1__state = -3;
<>2__current = new CodeInstruction(OpCodes.Call, (object)typeof(Minimap_Patches).GetMethod("GetExploreRadius", BindingFlags.Static | BindingFlags.NonPublic));
<>1__state = 3;
return true;
case 3:
<>1__state = -3;
<state>5__2 = TranspilerState.Finishing;
goto IL_01d7;
case 4:
<>1__state = -3;
<>2__current = <instruction>5__5;
<>1__state = 5;
return true;
case 5:
<>1__state = -3;
<state>5__2 = TranspilerState.Searching;
goto IL_01d7;
case 6:
{
<>1__state = -3;
goto IL_01ff;
}
IL_01d7:
<previous>5__3 = null;
goto IL_01ff;
IL_0206:
if (<>7__wrap3.MoveNext())
{
<instruction>5__5 = <>7__wrap3.Current;
switch (<state>5__2)
{
case TranspilerState.Searching:
if (<instruction>5__5.opcode == OpCodes.Ldarg_0)
{
<previous>5__3 = <instruction>5__5;
<state>5__2 = TranspilerState.Checking;
break;
}
<>2__current = <instruction>5__5;
<>1__state = 1;
return true;
case TranspilerState.Checking:
if (<instruction>5__5.opcode == OpCodes.Ldfld && ((FieldInfo)<instruction>5__5.operand).Name == "m_exploreRadius")
{
<>2__current = new CodeInstruction(OpCodes.Ldarg_2, (object)null);
<>1__state = 2;
return true;
}
<>2__current = <previous>5__3;
<>1__state = 4;
return true;
case TranspilerState.Finishing:
<>2__current = <instruction>5__5;
<>1__state = 6;
return true;
}
goto IL_01ff;
}
<>m__Finally1();
<>7__wrap3 = null;
return false;
IL_01ff:
<instruction>5__5 = null;
goto IL_0206;
}
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
if (<>7__wrap3 != null)
{
<>7__wrap3.Dispose();
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
{
<UpdateExplore_Transpiler>d__1 <UpdateExplore_Transpiler>d__;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
<UpdateExplore_Transpiler>d__ = this;
}
else
{
<UpdateExplore_Transpiler>d__ = new <UpdateExplore_Transpiler>d__1(0);
}
<UpdateExplore_Transpiler>d__.instructions = <>3__instructions;
return <UpdateExplore_Transpiler>d__;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<CodeInstruction>)this).GetEnumerator();
}
}
[IteratorStateMachine(typeof(<UpdateExplore_Transpiler>d__1))]
[HarmonyPatch("UpdateExplore")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> UpdateExplore_Transpiler(IEnumerable<CodeInstruction> instructions)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <UpdateExplore_Transpiler>d__1(-2)
{
<>3__instructions = instructions
};
}
private static float GetExploreRadius(Player player)
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
float num;
if (((Character)player).InInterior())
{
num = Mathf.Max(LandExploreRadius.Value * 0.2f, 10f);
sRadiusHudText.text = $"Pathfinder: radius={num:0.0}";
return num;
}
float num2 = 1f;
List<Player> list = new List<Player>();
Player.GetPlayersInRange(((Component)player).transform.position, 21f, list);
float num3 = ((!list.Any((Player p) => ((Character)p).IsAttachedToShip())) ? LandExploreRadius.Value : SeaExploreRadius.Value);
float num4 = Mathf.Max(GetColorMagnitude(EnvMan.instance.m_dirLight.color * EnvMan.instance.m_dirLight.intensity), GetColorMagnitude(RenderSettings.ambientLight));
num2 += (num4 - 1f) * DaylightRadiusScale.Value;
float num5 = 0f;
GameObject[] psystems = EnvMan.instance.GetCurrentEnvironment().m_psystems;
foreach (GameObject obj in psystems)
{
if (((Object)obj).name.Equals("Mist", StringComparison.InvariantCultureIgnoreCase))
{
num5 += 0.5f;
}
if (((Object)obj).name.Equals("SnowStorm", StringComparison.InvariantCultureIgnoreCase))
{
num5 += 0.7f * num4;
}
}
float num6 = Mathf.Clamp(RenderSettings.fogDensity * 10f + num5, 0f, 1.5f);
num2 -= num6 * WeatherRadiusScale.Value;
float num7 = Mathf.Clamp(((Component)player).transform.position.y - ZoneSystem.instance.m_waterLevel, 0f, 400f) / 100f * Mathf.Max(0.05f, 1f - num5);
num2 += num7 * AltitudeRadiusBonus.Value;
float locationModifier = GetLocationModifier(player, num7);
num2 += locationModifier;
if (num2 > 5f)
{
num2 = 5f;
}
if (num2 < 0.2f)
{
num2 = 0.2f;
}
num = Mathf.Clamp(num3 * num2, 20f, 2000f);
if (DisplayVariables.Value)
{
sVariablesHudText.text = string.Format("Pathfinder Variables\nRadius: {0:0.0}\nBase: {1:0.#}\nMultiplier: {2:0.000}\n\nLight: {3}\nWeather: {4}\nAltitude: {5}\nLocation: {6}", num, num3, num2, ((num4 - 1f) * DaylightRadiusScale.Value).ToString("+0.000;-0.000;0.000"), ((0f - num6) * WeatherRadiusScale.Value).ToString("+0.000;-0.000;0.000"), (num7 * AltitudeRadiusBonus.Value).ToString("+0.000;-0.000;0.000"), locationModifier.ToString("+0.000;-0.000;0.000"));
}
if (DisplayCurrentRadiusValue.Value)
{
sRadiusHudText.text = $"Pathfinder: radius={num:0.0}";
}
return num;
}
private static float GetColorMagnitude(Color color)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
return Mathf.Sqrt(color.r * color.r + color.g * color.g + color.b * color.b);
}
private static float GetLocationModifier(Player player, float altitude)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Invalid comparison between Unknown and I4
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Invalid comparison between Unknown and I4
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Invalid comparison between Unknown and I4
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
float num = ForestRadiusPenalty.Value + altitude * AltitudeRadiusBonus.Value * ForestRadiusPenalty.Value;
Biome currentBiome = player.GetCurrentBiome();
if ((int)currentBiome != 1)
{
if ((int)currentBiome != 8)
{
if ((int)currentBiome == 16)
{
return ((WorldGenerator.GetForestFactor(((Component)player).transform.position) < 0.8f) ? (0f - num) : 0f) + 0.1f * DaylightRadiusScale.Value;
}
return 0f;
}
return 0f - num - 0.25f * DaylightRadiusScale.Value;
}
if (!WorldGenerator.InForest(((Component)player).transform.position))
{
return 0f;
}
return 0f - num;
}
}
[HarmonyPatch(typeof(Hud))]
private static class Hud_Patches
{
[HarmonyPatch("Awake")]
[Harmony]
[HarmonyPostfix]
private static void Awake_Postfix(Hud __instance)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_012b: Expected O, but got Unknown
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_016d: Unknown result type (might be due to invalid IL or missing references)
//IL_0173: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: Unknown result type (might be due to invalid IL or missing references)
//IL_0175: Unknown result type (might be due to invalid IL or missing references)
//IL_017b: Unknown result type (might be due to invalid IL or missing references)
//IL_018c: Unknown result type (might be due to invalid IL or missing references)
//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0226: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("Pathfinder_RadiusText");
val.AddComponent<CanvasRenderer>();
val.transform.localPosition = Vector3.zero;
RectTransform obj = val.AddComponent<RectTransform>();
((Transform)obj).SetParent(__instance.m_rootObject.transform);
Vector2 val2 = default(Vector2);
((Vector2)(ref val2))..ctor(0f, 0f);
obj.anchorMax = val2;
Vector2 pivot = (obj.anchorMin = val2);
obj.pivot = pivot;
obj.offsetMin = new Vector2(10f, 5f);
obj.offsetMax = new Vector2(210f, 165f);
sRadiusHudText = val.AddComponent<Text>();
((Graphic)sRadiusHudText).raycastTarget = false;
sRadiusHudText.font = Font.CreateDynamicFontFromOSFont(new string[3] { "Segoe UI", "Helvetica", "Arial" }, 12);
sRadiusHudText.fontStyle = (FontStyle)1;
((Graphic)sRadiusHudText).color = Color.white;
sRadiusHudText.fontSize = 12;
sRadiusHudText.alignment = (TextAnchor)6;
((Shadow)val.AddComponent<Outline>()).effectColor = Color.black;
val.SetActive(DisplayCurrentRadiusValue.Value);
GameObject val4 = new GameObject("Pathfinder_VariableText");
val4.AddComponent<CanvasRenderer>();
val4.transform.localPosition = Vector3.zero;
RectTransform obj2 = val4.AddComponent<RectTransform>();
((Transform)obj2).SetParent(__instance.m_rootObject.transform);
((Vector2)(ref val2))..ctor(0f, 0f);
obj2.anchorMax = val2;
pivot = (obj2.anchorMin = val2);
obj2.pivot = pivot;
obj2.offsetMin = new Vector2(240f, 5f);
obj2.offsetMax = new Vector2(440f, 165f);
sVariablesHudText = val4.AddComponent<Text>();
((Graphic)sVariablesHudText).raycastTarget = false;
sVariablesHudText.font = Font.CreateDynamicFontFromOSFont(new string[3] { "Segoe UI", "Helvetica", "Arial" }, 12);
sVariablesHudText.fontStyle = (FontStyle)1;
((Graphic)sVariablesHudText).color = Color.white;
sVariablesHudText.fontSize = 12;
sVariablesHudText.alignment = (TextAnchor)6;
((Shadow)val4.AddComponent<Outline>()).effectColor = Color.black;
val4.SetActive(DisplayVariables.Value);
}
}
public const string ModId = "dev.crystal.pathfinder";
public static ConfigEntry<float> LandExploreRadius;
public static ConfigEntry<float> SeaExploreRadius;
public static ConfigEntry<float> AltitudeRadiusBonus;
public static ConfigEntry<float> ForestRadiusPenalty;
public static ConfigEntry<float> DaylightRadiusScale;
public static ConfigEntry<float> WeatherRadiusScale;
public static ConfigEntry<bool> DisplayCurrentRadiusValue;
public static ConfigEntry<bool> DisplayVariables;
private static Harmony sMinimapHarmony;
private static Harmony sHudHarmony;
private static Text sRadiusHudText;
private static Text sVariablesHudText;
static PathfinderPlugin()
{
}
private void Awake()
{
//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
//IL_01dc: Expected O, but got Unknown
//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
//IL_01eb: Expected O, but got Unknown
LandExploreRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Base", "LandExploreRadius", 200f, "The radius around the player to uncover while travelling on land near sea level. Higher values may cause performance issues. Max allowed is 2000. Game default is 100.");
LandExploreRadius.SettingChanged += Config_SettingChanged;
SeaExploreRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Base", "SeaExploreRadius", 300f, "The radius around the player to uncover while travelling on a boat. Higher values may cause performance issues. Max allowed is 2000. Game default is 100.");
SeaExploreRadius.SettingChanged += Config_SettingChanged;
AltitudeRadiusBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Multipliers", "AltitudeRadiusBonus", 0.5f, "Bonus multiplier to apply to land exploration radius based on altitude. For every 100 units above sea level (smooth scale), add this value multiplied by LandExploreRadius to the total. For example, with a radius of 200 and a multiplier of 0.5, radius is 200 at sea level, 250 at 50 altitude, 300 at 100 altitude, 400 at 200 altitude, etc. For reference, a typical mountain peak is around 170 altitude. Accepted range 0-2. Set to 0 to disable.");
AltitudeRadiusBonus.SettingChanged += Config_SettingChanged;
ForestRadiusPenalty = ((BaseUnityPlugin)this).Config.Bind<float>("Multipliers", "ForestRadiusPenalty", 0.3f, "Penalty to apply to land exploration radius when in a forest (black forest, forested parts of meadows and plains). This value is multiplied by the base land exploration radius and subtraced from the total. Accepted range 0-1. Set to 0 to disable.");
ForestRadiusPenalty.SettingChanged += Config_SettingChanged;
DaylightRadiusScale = ((BaseUnityPlugin)this).Config.Bind<float>("Multipliers", "DaylightRadiusScale", 0.2f, "Influences how much daylight (directional and ambient light) affects exploration radius. This value is multiplied by the base land or sea exploration radius and added to the total. Accepted range 0-1. Set to 0 to disable.");
DaylightRadiusScale.SettingChanged += Config_SettingChanged;
WeatherRadiusScale = ((BaseUnityPlugin)this).Config.Bind<float>("Multipliers", "WeatherRadiusScale", 0.5f, "Influences how much the current weather affects exploration radius. This value is multiplied by the base land or sea exploration radius and added to the total. Accepted range 0-1. Set to 0 to disable.");
WeatherRadiusScale.SettingChanged += Config_SettingChanged;
DisplayCurrentRadiusValue = ((BaseUnityPlugin)this).Config.Bind<bool>("Miscellaneous", "DisplayCurrentRadiusValue", false, "Enabling this will display the currently computed exploration radius in the bottom left of the in-game Hud. Useful if you are trying to tweak config values and want to see the result.");
DisplayCurrentRadiusValue.SettingChanged += DisplayRadiusValue_SettingChanged;
DisplayVariables = ((BaseUnityPlugin)this).Config.Bind<bool>("Miscellaneous", "DisplayVariables", false, "Enabling this will display on the Hud the values of various variables that go into calculating the exploration radius. Mostly useful for debugging and tweaking the config.");
DisplayVariables.SettingChanged += DisplayVariablesValue_SettingChanged;
ClampConfig();
sMinimapHarmony = new Harmony("dev.crystal.pathfinder_Minimap");
sHudHarmony = new Harmony("dev.crystal.pathfinder_Hud");
sMinimapHarmony.PatchAll(typeof(Minimap_Patches));
sHudHarmony.PatchAll(typeof(Hud_Patches));
}
private void Config_SettingChanged(object sender, EventArgs e)
{
ClampConfig();
}
private void DisplayRadiusValue_SettingChanged(object sender, EventArgs e)
{
((Component)sRadiusHudText).gameObject.SetActive(DisplayCurrentRadiusValue.Value);
if (!DisplayCurrentRadiusValue.Value)
{
sRadiusHudText.text = string.Empty;
}
}
private void DisplayVariablesValue_SettingChanged(object sender, EventArgs e)
{
((Component)sVariablesHudText).gameObject.SetActive(DisplayVariables.Value);
if (!DisplayVariables.Value)
{
sVariablesHudText.text = string.Empty;
}
}
private void OnDestroy()
{
sMinimapHarmony.UnpatchSelf();
sHudHarmony.UnpatchSelf();
}
private static void ClampConfig()
{
if (LandExploreRadius.Value < 0f)
{
LandExploreRadius.Value = 0f;
}
if (LandExploreRadius.Value > 2000f)
{
LandExploreRadius.Value = 2000f;
}
if (SeaExploreRadius.Value < 0f)
{
SeaExploreRadius.Value = 0f;
}
if (SeaExploreRadius.Value > 2000f)
{
SeaExploreRadius.Value = 2000f;
}
if (AltitudeRadiusBonus.Value < 0f)
{
AltitudeRadiusBonus.Value = 0f;
}
if (AltitudeRadiusBonus.Value > 2f)
{
AltitudeRadiusBonus.Value = 2f;
}
if (ForestRadiusPenalty.Value < 0f)
{
ForestRadiusPenalty.Value = 0f;
}
if (ForestRadiusPenalty.Value > 1f)
{
ForestRadiusPenalty.Value = 1f;
}
if (DaylightRadiusScale.Value < 0f)
{
DaylightRadiusScale.Value = 0f;
}
if (DaylightRadiusScale.Value > 1f)
{
DaylightRadiusScale.Value = 1f;
}
if (WeatherRadiusScale.Value < 0f)
{
WeatherRadiusScale.Value = 0f;
}
if (WeatherRadiusScale.Value > 1f)
{
WeatherRadiusScale.Value = 1f;
}
}
}