using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using InscryptionWarning.Patches;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("InscryptionWarning")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.1.0")]
[assembly: AssemblyInformationalVersion("0.2.1+34b502e7d78e490fd914d126c6c8849c0fb1bc61")]
[assembly: AssemblyProduct("InscryptionWarning")]
[assembly: AssemblyTitle("InscryptionWarning")]
[assembly: AssemblyVersion("0.2.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace InscryptionWarning
{
[BepInPlugin("InscryptionWarning", "InscryptionWarning", "0.2.1")]
public class Plugin : BaseUnityPlugin
{
internal static ManualLogSource Logger = new ManualLogSource("InscryptionWarning");
public void Awake()
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
Logger = ((BaseUnityPlugin)this).Logger;
Logger.LogInfo((object)"Plugin InscryptionWarning is loaded!");
MapHintPatch.Init(((BaseUnityPlugin)this).Config);
new Harmony("InscryptionWarning").PatchAll();
}
public void Update()
{
MapHintPatch.Tick();
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "InscryptionWarning";
public const string PLUGIN_NAME = "InscryptionWarning";
public const string PLUGIN_VERSION = "0.2.1";
}
}
namespace InscryptionWarning.Patches
{
internal sealed class SharedNodeMarker : MonoBehaviour
{
}
internal static class MapHintPatch
{
internal enum CueColor
{
Gold,
Red,
Blue
}
internal enum CueStyle
{
Off,
Diegetic,
Icon,
Debug
}
private static class EventStartLocator
{
private static readonly MethodInfo? ActiveSaveDataGetter = AccessTools.PropertyGetter(typeof(SaveManager), "ActiveSaveData");
private static readonly FieldInfo? ConditionsField = AccessTools.Field(typeof(FollowupEventState), "conditions");
private static readonly FieldInfo? ConditionDataField = AccessTools.Field(typeof(FollowupConditionState), "data");
private static readonly FieldInfo? StartDistanceField = AccessTools.Field(typeof(FollowupConditionState), "startDistance");
private static int resolvedFrame = -1;
private static int? cached;
internal static bool Available
{
get
{
if (ActiveSaveDataGetter != null && ConditionsField != null && ConditionDataField != null)
{
return StartDistanceField != null;
}
return false;
}
}
internal static void LogAvailability()
{
if (!Available)
{
Plugin.Logger.LogError((object)("Cannot read the Inscryption event's start distance from the save — the game's internals have moved. No hint will be shown. Missing: " + $"SaveManager.ActiveSaveData={ActiveSaveDataGetter != null}, " + $"FollowupEventState.conditions={ConditionsField != null}, " + $"FollowupConditionState.data={ConditionDataField != null}, " + $"FollowupConditionState.startDistance={StartDistanceField != null}"));
}
}
internal static int? Resolve(SaveManager saveManager)
{
if (resolvedFrame == Time.frameCount)
{
return cached;
}
resolvedFrame = Time.frameCount;
int? num = Lookup(saveManager);
if (num != cached)
{
Plugin.Logger.LogInfo((object)((!num.HasValue) ? $"Inscryption followup no longer active (was startDistance={cached})." : $"Inscryption followup active: startDistance={num}."));
cached = num;
}
return cached;
}
private static int? Lookup(SaveManager saveManager)
{
if (!Available)
{
return null;
}
object? obj = ActiveSaveDataGetter.Invoke(saveManager, null);
SaveData val = (SaveData)((obj is SaveData) ? obj : null);
if (val == null)
{
return null;
}
List<FollowupEventState> activeFollowupEvents = val.GetActiveFollowupEvents();
if (activeFollowupEvents == null)
{
return null;
}
int? num = null;
foreach (FollowupEventState item in activeFollowupEvents)
{
if (item == null || !(ConditionsField.GetValue(item) is IEnumerable enumerable))
{
continue;
}
foreach (object item2 in enumerable)
{
if (item2 == null)
{
continue;
}
object? value = ConditionDataField.GetValue(item2);
FollowupConditionData val2 = (FollowupConditionData)((value is FollowupConditionData) ? value : null);
if (val2 != null && !(val2.ConditionName != "FollowupConditionInscryptionEvent"))
{
int num2 = (int)StartDistanceField.GetValue(item2);
if (!num.HasValue || num2 > num)
{
num = num2;
}
}
}
}
return num;
}
}
[HarmonyPatch(typeof(MapSection), "SetUpNodesOnBranch")]
private static class MarkSharedNodes
{
private static void Postfix(List<MapNodeUI> availableNodes, BranchSelection branch)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Invalid comparison between Unknown and I4
if ((int)branch != -1 || availableNodes == null)
{
return;
}
foreach (MapNodeUI availableNode in availableNodes)
{
if ((Object)(object)availableNode != (Object)null && (Object)(object)((Component)availableNode).GetComponent<SharedNodeMarker>() == (Object)null)
{
((Component)availableNode).gameObject.AddComponent<SharedNodeMarker>();
}
}
}
}
[HarmonyPatch(typeof(MapNodeUI), "RefreshState")]
private static class HintNode
{
private static void Postfix(MapNodeUI __instance, SaveManager saveManager)
{
lastSaveManager = saveManager;
GameObject orCreateOverlay = GetOrCreateOverlay(__instance);
if (!ShouldShowHint(__instance, saveManager))
{
orCreateOverlay.SetActive(false);
return;
}
ApplyStyle(orCreateOverlay);
orCreateOverlay.SetActive(true);
}
}
private const string OverlayName = "InscryptionWarning_Hint";
private const int GlowTextureSize = 128;
private const float ConfigPollSeconds = 1f;
private const float GlowCoreRadius = 0.2f;
private const float DiegeticHaloScale = 1.5f;
private static ConfigEntry<CueStyle> style = null;
private static ConfigFile configFile = null;
private static ConfigEntry<CueColor> cueColor = null;
private static ConfigEntry<float> diegeticStrength = null;
private static ConfigEntry<bool> verboseLogging = null;
private static Sprite? softGlowSprite;
private static readonly List<MapNodeUI> hintedNodes = new List<MapNodeUI>();
private static SaveManager? lastSaveManager;
private static DateTime configWriteTime;
private static float nextConfigPoll;
private static int loggedPlanFor = int.MinValue;
public static void Init(ConfigFile config)
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Expected O, but got Unknown
configFile = config;
style = config.Bind<CueStyle>("Hint", "CueStyle", CueStyle.Diegetic, "How obvious the Inscryption path hint should be on the map: Off (disabled), Diegetic (a soft halo behind the correct node), Icon (a small visible badge), Debug (an unmissable magenta marker, for diagnosing rather than playing).");
cueColor = config.Bind<CueColor>("Hint", "CueColor", CueColor.Gold, "Colour of the Diegetic halo and the Icon badge: Gold (the original warm tint), Red, or Blue. Debug keeps its own magenta marker so it always stands out no matter what this is set to.");
diegeticStrength = config.Bind<float>("Hint", "DiegeticStrength", 0.6f, new ConfigDescription("Opacity of the Diegetic halo across its core and at the node icon's edge, fading to nothing at the halo's rim. Other cue styles ignore this.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
verboseLogging = config.Bind<bool>("Diagnostics", "VerboseLogging", false, "Log a line for every map node the hint is evaluated against. Very chatty — one burst per map refresh — so it is meant for diagnosing a missing cue, not for normal play. State changes (event found/lost, code, branch plan) are logged either way.");
configWriteTime = ReadConfigWriteTime();
EventStartLocator.LogAvailability();
SelfCheck();
Plugin.Logger.LogInfo((object)($"MapHintPatch ready: CueStyle={style.Value}, CueColor={cueColor.Value}, " + $"DiegeticStrength={diegeticStrength.Value}, " + $"VerboseLogging={verboseLogging.Value}"));
if (style.Value == CueStyle.Off)
{
Plugin.Logger.LogWarning((object)"CueStyle is Off — no hint will ever be drawn.");
}
}
internal static void Tick()
{
if (!(Time.realtimeSinceStartup < nextConfigPoll))
{
nextConfigPoll = Time.realtimeSinceStartup + 1f;
DateTime dateTime = ReadConfigWriteTime();
if (!(dateTime == configWriteTime))
{
configWriteTime = dateTime;
ReloadConfig();
}
}
}
private static DateTime ReadConfigWriteTime()
{
try
{
return File.GetLastWriteTimeUtc(configFile.ConfigFilePath);
}
catch (Exception ex)
{
Plugin.Logger.LogDebug((object)("Could not stat the config file: " + ex.Message));
return configWriteTime;
}
}
private static void ReloadConfig()
{
(CueStyle, CueColor, float, bool) tuple = (style.Value, cueColor.Value, diegeticStrength.Value, verboseLogging.Value);
try
{
configFile.Reload();
}
catch (Exception ex)
{
Plugin.Logger.LogWarning((object)("Could not reload the config file: " + ex.Message));
return;
}
(CueStyle, CueColor, float, bool) other = (style.Value, cueColor.Value, diegeticStrength.Value, verboseLogging.Value);
if (!tuple.Equals(other))
{
Plugin.Logger.LogInfo((object)($"Config reloaded: CueStyle={style.Value}, CueColor={cueColor.Value}, " + $"DiegeticStrength={diegeticStrength.Value}, VerboseLogging={verboseLogging.Value}"));
RefreshLiveOverlays();
}
}
private static void RefreshLiveOverlays()
{
for (int num = hintedNodes.Count - 1; num >= 0; num--)
{
MapNodeUI val = hintedNodes[num];
if ((Object)(object)val == (Object)null)
{
hintedNodes.RemoveAt(num);
}
else
{
Transform val2 = ((Component)val).transform.Find("InscryptionWarning_Hint");
if ((Object)(object)val2 == (Object)null)
{
hintedNodes.RemoveAt(num);
}
else if ((Object)(object)lastSaveManager != (Object)null && ShouldShowHint(val, lastSaveManager))
{
ApplyStyle(((Component)val2).gameObject);
((Component)val2).gameObject.SetActive(true);
}
else
{
((Component)val2).gameObject.SetActive(false);
}
}
}
}
internal static BranchSelection? GetHintedBranch(int startDistance, int nodeDistance, int code)
{
int num = nodeDistance - (startDistance + 1);
if (num < 0 || num > 2)
{
return null;
}
return (BranchSelection)((((code >> 2 - num) & 1) != 0) ? 1 : 0);
}
private static void SelfCheck()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Invalid comparison between Unknown and I4
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//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_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Invalid comparison between Unknown and I4
if ((int)GetHintedBranch(10, 11, 5).GetValueOrDefault() != 1 || GetHintedBranch(10, 12, 5) != (BranchSelection?)0 || (int)GetHintedBranch(10, 13, 5).GetValueOrDefault() != 1 || GetHintedBranch(10, 10, 5).HasValue || GetHintedBranch(10, 14, 5).HasValue)
{
throw new InvalidOperationException("MapHintPatch.GetHintedBranch self-check failed");
}
}
private static void LogBranchPlan(int startDistance, int code)
{
int num = startDistance * 8 + code;
if (loggedPlanFor != num)
{
loggedPlanFor = num;
string text = string.Empty;
for (int i = 1; i <= 3; i++)
{
BranchSelection? hintedBranch = GetHintedBranch(startDistance, startDistance + i, code);
text += $" d{startDistance + i}={hintedBranch}";
}
Plugin.Logger.LogInfo((object)($"Inscryption path code={code} (binary {Convert.ToString(code, 2).PadLeft(3, '0')}), " + $"startDistance={startDistance}, hinting:{text}"));
}
}
private static bool ShouldShowHint(MapNodeUI node, SaveManager saveManager)
{
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_0160: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
if (style.Value == CueStyle.Off || (Object)(object)saveManager == (Object)null)
{
return false;
}
int? num = EventStartLocator.Resolve(saveManager);
if (!num.HasValue)
{
return false;
}
if (saveManager.GetInscryptionEventSuccessfullyCompleted())
{
return false;
}
Location location = node.GetLocation();
if (location == null)
{
if (verboseLogging.Value)
{
Plugin.Logger.LogDebug((object)("Node '" + ((Object)node).name + "' has no location — skipped."));
}
return false;
}
if ((Object)(object)((Component)node).GetComponent<SharedNodeMarker>() != (Object)null)
{
if (verboseLogging.Value)
{
Plugin.Logger.LogDebug((object)($"Node '{((Object)node).name}' distance={location.Distance} is shared/pact " + "(GetBranch() reports LeftBranch for these regardless) -> hide"));
}
return false;
}
int inscryptionEventPath = saveManager.GetInscryptionEventPath();
LogBranchPlan(num.Value, inscryptionEventPath);
BranchSelection? hintedBranch = GetHintedBranch(num.Value, location.Distance, inscryptionEventPath);
bool flag = hintedBranch.HasValue && (BranchSelection?)node.GetBranch() == hintedBranch;
if (verboseLogging.Value)
{
Plugin.Logger.LogDebug((object)($"Node '{((Object)node).name}' distance={location.Distance} branch={node.GetBranch()} " + "hinted=" + ((hintedBranch.HasValue ? ((object)hintedBranch.GetValueOrDefault()/*cast due to .constrained prefix*/).ToString() : null) ?? "none") + " -> " + (flag ? "SHOW" : "hide")));
}
return flag;
}
private static GameObject GetOrCreateOverlay(MapNodeUI node)
{
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Expected O, but got Unknown
Transform val = ((Component)node).transform.Find("InscryptionWarning_Hint");
if ((Object)(object)val != (Object)null)
{
return ((Component)val).gameObject;
}
GameObject val2 = new GameObject("InscryptionWarning_Hint", new Type[2]
{
typeof(RectTransform),
typeof(Image)
});
val2.transform.SetParent(((Component)node).transform, false);
((Graphic)val2.GetComponent<Image>()).raycastTarget = false;
hintedNodes.Add(node);
return val2;
}
private static Sprite GetSoftGlowSprite()
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Expected O, but got Unknown
//IL_012b: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)softGlowSprite != (Object)null)
{
return softGlowSprite;
}
Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false)
{
name = "InscryptionWarning_Hint_Glow",
wrapMode = (TextureWrapMode)1,
filterMode = (FilterMode)1,
hideFlags = (HideFlags)61
};
Color32[] array = (Color32[])(object)new Color32[16384];
float num = 63.5f;
for (int i = 0; i < 128; i++)
{
for (int j = 0; j < 128; j++)
{
float num2 = ((float)j - num) / num;
float num3 = ((float)i - num) / num;
float num4 = Mathf.Clamp01(Mathf.Sqrt(num2 * num2 + num3 * num3));
float num5 = Mathf.InverseLerp(0.2f, 1f, num4);
float num6 = Mathf.SmoothStep(0f, 1f, 1f - num5);
array[i * 128 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)Mathf.RoundToInt(num6 * 255f));
}
}
val.SetPixels32(array);
val.Apply(false);
softGlowSprite = Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0);
((Object)softGlowSprite).hideFlags = (HideFlags)61;
return softGlowSprite;
}
private static Color ResolveCueColor(float alpha)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
Color result = (Color)(cueColor.Value switch
{
CueColor.Gold => new Color(1f, 0.85f, 0.3f),
CueColor.Blue => new Color(0.25f, 0.55f, 1f),
_ => new Color(1f, 0.15f, 0.12f),
});
result.a = alpha;
return result;
}
private static void ApplyStyle(GameObject overlay)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_015d: Unknown result type (might be due to invalid IL or missing references)
//IL_0168: Unknown result type (might be due to invalid IL or missing references)
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
RectTransform val = (RectTransform)overlay.transform;
Image component = overlay.GetComponent<Image>();
switch (style.Value)
{
case CueStyle.Icon:
overlay.transform.SetAsLastSibling();
component.sprite = null;
val.anchorMin = new Vector2(0.5f, 1f);
val.anchorMax = new Vector2(0.5f, 1f);
val.pivot = new Vector2(0.5f, 0.5f);
val.sizeDelta = new Vector2(20f, 20f);
val.anchoredPosition = Vector2.zero;
((Graphic)component).color = ResolveCueColor(0.95f);
break;
case CueStyle.Debug:
overlay.transform.SetAsLastSibling();
component.sprite = null;
val.anchorMin = Vector2.zero;
val.anchorMax = Vector2.one;
val.offsetMin = Vector2.zero;
val.offsetMax = Vector2.zero;
((Graphic)component).color = new Color(1f, 0.1f, 0.9f, 0.8f);
break;
default:
{
overlay.transform.SetAsFirstSibling();
component.sprite = GetSoftGlowSprite();
float num = 0.25f;
val.anchorMin = new Vector2(0f - num, 0f - num);
val.anchorMax = new Vector2(1f + num, 1f + num);
val.offsetMin = Vector2.zero;
val.offsetMax = Vector2.zero;
((Graphic)component).color = ResolveCueColor(diegeticStrength.Value);
break;
}
}
}
}
}