using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using ShinyShoe;
using TMPro;
using UITweaks.DeckColumns;
using UITweaks.ForgeSmartToggle;
using UITweaks.GreedBlights;
using UITweaks.InscryptionWarning;
using UITweaks.JudgesScales;
using UITweaks.RerollConfirmation;
using UITweaks.TitanTransitions;
using UnityEngine;
using UnityEngine.EventSystems;
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("UITweaks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+968cf9f39c6e024ea465ebe3c3c99dc150138de2")]
[assembly: AssemblyProduct("UITweaks")]
[assembly: AssemblyTitle("UITweaks")]
[assembly: AssemblyVersion("0.1.0.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 UITweaks
{
[BepInPlugin("SpecialCircumstances.UITweaks", "UITweaks", "0.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
internal static ManualLogSource Logger = new ManualLogSource("SpecialCircumstances.UITweaks");
private const float ConfigPollSeconds = 1f;
private DateTime configWriteTime;
private float nextConfigPoll;
private Harmony harmony;
public void Awake()
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Expected O, but got Unknown
Logger = ((BaseUnityPlugin)this).Logger;
harmony = new Harmony("SpecialCircumstances.UITweaks");
Feature("ForgeSmartToggle", "ForgeSmartToggle", delegate
{
HybridForgePatch.Init(((BaseUnityPlugin)this).Config);
});
Feature("InscryptionWarning", "InscryptionWarning", delegate
{
MapHintPatch.Init(((BaseUnityPlugin)this).Config);
});
Feature("RerollConfirmation", "RerollConfirmation", delegate
{
RerollGoldThreshold.Init(((BaseUnityPlugin)this).Config);
});
Feature("JudgesScales", null, delegate
{
JudgesScalesHandSelection.Init(((BaseUnityPlugin)this).Config);
});
Feature("TitanTransitions", null, delegate
{
UITweaks.TitanTransitions.TitanTransitions.Init(((BaseUnityPlugin)this).Config);
});
Feature("GreedBlights", null, delegate
{
GreedBlightAura.Init(((BaseUnityPlugin)this).Config);
});
Feature("DeckColumns", null, delegate
{
UITweaks.DeckColumns.DeckColumns.Init(((BaseUnityPlugin)this).Config);
});
configWriteTime = ReadConfigWriteTime();
Logger.LogInfo((object)"Plugin SpecialCircumstances.UITweaks is loaded!");
}
private void Feature(string name, string? standaloneGuid, Action init)
{
init();
if (standaloneGuid != null && IsLoaded(standaloneGuid))
{
Logger.LogInfo((object)(name + ": off, the " + standaloneGuid + " plugin is loaded and provides it."));
return;
}
string text = "UITweaks." + name;
Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(typeof(Plugin).Assembly);
foreach (Type type in typesFromAssembly)
{
if (type.Namespace == text)
{
harmony.PatchAll(type);
}
}
}
private static bool IsLoaded(string standaloneGuid)
{
if (!Chainloader.PluginInfos.ContainsKey(standaloneGuid))
{
return Chainloader.PluginInfos.ContainsKey("SpecialCircumstances." + standaloneGuid);
}
return true;
}
public void Update()
{
PollConfig();
JudgesScalesHandSelection.KeepDiscardButtonSelected();
}
private void PollConfig()
{
if (Time.realtimeSinceStartup < nextConfigPoll)
{
return;
}
nextConfigPoll = Time.realtimeSinceStartup + 1f;
DateTime dateTime = ReadConfigWriteTime();
if (!(dateTime == configWriteTime))
{
configWriteTime = dateTime;
try
{
((BaseUnityPlugin)this).Config.Reload();
}
catch (Exception ex)
{
Logger.LogWarning((object)("Could not reload the config file: " + ex.Message));
return;
}
configWriteTime = ReadConfigWriteTime();
Logger.LogDebug((object)"Config reloaded.");
}
}
private DateTime ReadConfigWriteTime()
{
try
{
return File.GetLastWriteTimeUtc(((BaseUnityPlugin)this).Config.ConfigFilePath);
}
catch (Exception ex)
{
Logger.LogDebug((object)("Could not stat the config file: " + ex.Message));
return configWriteTime;
}
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "SpecialCircumstances.UITweaks";
public const string PLUGIN_NAME = "UITweaks";
public const string PLUGIN_VERSION = "0.1.0";
}
}
namespace UITweaks.TitanTransitions
{
internal static class TitanTransitions
{
[HarmonyPatch(typeof(TimeScaleManager), "RefreshTimeScale")]
private static class Multiply
{
private static void Postfix()
{
if (boosting && Enabled.Value)
{
Time.timeScale *= speedFactor.Value;
}
}
}
[HarmonyPatch(typeof(MapScreen), "TransitionOutOfBattle")]
private static class MapSkipped
{
private static bool Prefix(MapScreen __instance, SaveManager ___saveManager, RelicManager ___relicManager, GameStateManager ___gameStateManager)
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: 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_0045: Invalid comparison between Unknown and I4
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Invalid comparison between Unknown and I4
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Invalid comparison between Unknown and I4
if (!Enabled.Value || (Object)(object)___saveManager == (Object)null)
{
return true;
}
VictorySectionState victorySectionState = ___saveManager.GetVictorySectionState();
if ((int)victorySectionState != 1)
{
if ((int)victorySectionState == 2 && (int)___saveManager.GetVictoryTypeAfterGameOver() == 2)
{
Plugin.Logger.LogDebug((object)"Titan transition: skipping the map's victory lap, ending the run.");
___saveManager.SetGameSequence((GameSequence)3, true);
((MonoBehaviour)__instance).StartCoroutine(NextFrame(delegate
{
___gameStateManager.EndGame((EndGameReason)0);
}));
return false;
}
return true;
}
Plugin.Logger.LogDebug((object)"Titan transition: skipping the map's run-up, loading the battle.");
___saveManager.SetGameSequence((GameSequence)3, true);
((MonoBehaviour)__instance).StartCoroutine(NextFrame(delegate
{
___relicManager.ApplyDepartDestinationRelicEffects();
___saveManager.LoadScenario();
}));
return false;
}
private static IEnumerator NextFrame(Action action)
{
yield return null;
action();
}
}
[HarmonyPatch(typeof(MapScreen), "Initialize")]
private static class VictoryLap
{
private static void Postfix(SaveManager ___saveManager)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Invalid comparison between Unknown and I4
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Invalid comparison between Unknown and I4
Boost((Object)(object)___saveManager != (Object)null && (int)___saveManager.GetVictorySectionState() == 2 && (int)___saveManager.GetVictoryTypeAfterGameOver() != 2);
}
}
[HarmonyPatch(typeof(GameStateManager), "EndGame")]
private static class RunOver
{
private static void Prefix()
{
Boost(on: false);
}
}
[HarmonyPatch(typeof(CombatManager), "StartCombat")]
private static class BattleStart
{
private static void Prefix()
{
Boost(on: false);
}
}
[HarmonyPatch(typeof(HeroManager), "BeginInitialSpawn")]
private static class BattleOpening
{
private static IEnumerator Postfix(IEnumerator __result, HeroManager __instance)
{
if (!__instance.IsTrueFinalBoss)
{
return __result;
}
return Sped(__result);
}
}
[HarmonyPatch(typeof(HeroManager), "DoTrueFinalBossSpawning")]
private static class TitanArrival
{
private static IEnumerator Postfix(IEnumerator __result)
{
return Sped(__result);
}
}
[HarmonyPatch(typeof(HeroManager), "PerformHellforgedBossRelentlessAction")]
private static class FloorsTornDown
{
private static IEnumerator Postfix(IEnumerator __result)
{
return Sped(__result);
}
}
[HarmonyPatch(typeof(CombatManager), "ShowKillCam")]
private static class TitanFalls
{
private static void Prefix(CharacterState killedCharacter)
{
if ((Object)(object)killedCharacter != (Object)null && killedCharacter.IsTrueFinalBoss())
{
Boost(on: true);
}
}
}
[HarmonyPatch(typeof(GameScreen), "ShowVictoryUI")]
private static class VictoryScreen
{
private static void Prefix()
{
Boost(on: false);
}
}
internal const string Section = "TitanTransitions";
internal static ConfigEntry<bool> Enabled;
private static ConfigEntry<float> speedFactor;
private static bool boosting;
public static void Init(ConfigFile config)
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Expected O, but got Unknown
Enabled = config.Bind<bool>("TitanTransitions", "Enabled", true, "Skip the map's run-up to the Titan and its victory lap after the Titan falls, and speed the Titan's arrival, the floors it destroys and its death up in the battle.");
speedFactor = config.Bind<float>("TitanTransitions", "SpeedFactor", 5f, new ConfigDescription("How many times faster the sped-up sequences run. 1 is the game's own pace.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), Array.Empty<object>()));
}
internal static void Boost(bool on)
{
if (boosting == on)
{
return;
}
boosting = on;
Plugin.Logger.LogDebug((object)(on ? "Titan transition: speeding up." : "Titan transition: normal speed."));
AllGameManagers instance = AllGameManagers.Instance;
if (instance != null)
{
TimeScaleManager timeScaleManager = instance.GetTimeScaleManager();
if (timeScaleManager != null)
{
timeScaleManager.RefreshTimeScale();
}
}
}
private static IEnumerator Sped(IEnumerator inner)
{
Boost(on: true);
try
{
while (inner.MoveNext())
{
yield return inner.Current;
}
}
finally
{
Boost(on: false);
}
}
}
}
namespace UITweaks.RerollConfirmation
{
[HarmonyPatch(typeof(BuyButton), "Refresh")]
internal static class BuyButton_RerollWarning_Patch
{
private const string WarningSuffix = " <color=#FF3B3B><b>!</b></color>";
private static void Postfix(BuyButton __instance)
{
if (!RerollGoldThreshold.Enabled.Value)
{
return;
}
MerchantGoodUIBase componentInParent = ((Component)__instance).GetComponentInParent<MerchantGoodUIBase>();
object obj;
if (componentInParent == null)
{
obj = null;
}
else
{
MerchantGoodState goodState = componentInParent.GoodState;
obj = ((goodState != null) ? ((RewardState)goodState).RewardData : null);
}
if (!(obj is RerollMerchantRewardData) || !componentInParent.Affordable)
{
return;
}
AllGameManagers instance = AllGameManagers.Instance;
SaveManager val = ((instance != null) ? instance.GetSaveManager() : null);
if ((Object)(object)val == (Object)null)
{
return;
}
Traverse val2 = Traverse.Create((object)__instance);
TMP_Text value = val2.Field<TMP_Text>("label").Value;
if (!((Object)(object)value == (Object)null))
{
MerchantData value2 = Traverse.Create((object)componentInParent).Field<MerchantData>("merchantData").Value;
if (val.GetGold() - val2.Field<int>("cost").Value < RerollGoldThreshold.GetMinimumGoldAfterReroll(value2, val))
{
value.text += " <color=#FF3B3B><b>!</b></color>";
}
}
}
}
[HarmonyPatch(typeof(MerchantScreen), "TryPurchase")]
internal static class MerchantScreen_RerollConfirmation_Patch
{
private static bool suppressConfirmation;
private static bool Prefix(MerchantScreen __instance, MerchantGoodUIBase goodUI)
{
if (suppressConfirmation || !RerollGoldThreshold.Enabled.Value)
{
return true;
}
MerchantGoodUIBase obj = goodUI;
object obj2;
if (obj == null)
{
obj2 = null;
}
else
{
MerchantGoodState goodState = obj.GoodState;
obj2 = ((goodState != null) ? ((RewardState)goodState).RewardData : null);
}
if (!(obj2 is RerollMerchantRewardData))
{
return true;
}
SaveManager value = Traverse.Create((object)__instance).Field<SaveManager>("saveManager").Value;
MerchantData value2 = Traverse.Create((object)__instance).Field<MerchantData>("sourceMerchantData").Value;
int cost = goodUI.GoodState.GetCost(value2);
if (!value.CanAfford(cost))
{
return true;
}
int num = value.GetGold() - cost;
int minimumGoldAfterReroll = RerollGoldThreshold.GetMinimumGoldAfterReroll(value2, value);
if (num >= minimumGoldAfterReroll)
{
return true;
}
Traverse.Create((object)__instance).Field<ScreenManager>("screenManager").Value.ShowConfirmationDialog($"Rerolling will leave you with only {num} gold. Reroll anyway?", (Action)delegate
{
suppressConfirmation = true;
try
{
Traverse.Create((object)__instance).Method("TryPurchase", new object[1] { goodUI }).GetValue();
}
finally
{
suppressConfirmation = false;
}
}, (Action)null, (Anchor)0, false);
return false;
}
}
internal static class RerollGoldThreshold
{
internal const string Section = "RerollConfirmation";
internal static ConfigEntry<bool> Enabled;
private static ConfigEntry<int> trinketShopThreshold;
private static ConfigEntry<int> otherShopThreshold;
private const string TrinketShopAssetNameMarker = "ArtifactMerchant";
private const string GuildMarkerRelicAssetKey = "CheaperMerchants";
private const double GuildMarkerDiscountMultiplier = 0.75;
public static void Init(ConfigFile config)
{
Enabled = config.Bind<bool>("RerollConfirmation", "Enabled", true, "Warn before a shop reroll drops gold below the shop's minimum: a red ! on the reroll button, then a confirmation dialog.");
trinketShopThreshold = config.Bind<int>("RerollConfirmation", "TrinketShopMinimumGold", 135, "Minimum gold to keep after a reroll at the Trinket (Merchant of Trinkets) shop before warning.");
otherShopThreshold = config.Bind<int>("RerollConfirmation", "OtherShopMinimumGold", 90, "Minimum gold to keep after a reroll at other shops (Card/Steel/Arms/Magic) before warning.");
}
public static int GetMinimumGoldAfterReroll(MerchantData? merchantData, SaveManager? saveManager)
{
int num = (((Object)(object)merchantData != (Object)null && ((Object)merchantData).name.Contains("ArtifactMerchant")) ? trinketShopThreshold.Value : otherShopThreshold.Value);
if (!((Object)(object)saveManager != (Object)null) || !saveManager.GetAllRelics().Any((RelicState relic) => relic.GetAssetName() == "CheaperMerchants"))
{
return num;
}
return (int)Math.Round((double)num * 0.75);
}
}
}
namespace UITweaks.JudgesScales
{
internal static class JudgesScalesHandSelection
{
internal const string Section = "JudgesScales";
internal static ConfigEntry<bool> Enabled = null;
private static ConfigEntry<string> selectedCardTint = null;
internal static bool Active;
internal static readonly List<CardState> Selected = new List<CardState>();
internal static GameUISelectableButton? ConfirmButton;
internal static HandUI? Hand;
private static readonly FieldInfo FocusedCardUI = AccessTools.Field(typeof(HandUI), "focusedCardUI");
private static readonly FieldInfo CardFrontTinter = AccessTools.Field(typeof(CardUI), "cardFrontTinter");
private static readonly FieldInfo GraphicsToTint = AccessTools.Field(typeof(ContentTinter), "graphicsToTint");
private static readonly FieldInfo TintColor = AccessTools.Field(typeof(ContentTinter), "tintColor");
private static readonly FieldInfo OverlaysToShow = AccessTools.Field(typeof(ContentTinter), "overlaysToShow");
private static readonly FieldInfo OverlayColor = AccessTools.Field(typeof(ContentTinter), "overlayColor");
private static readonly FieldInfo ControlChildTinters = AccessTools.Field(typeof(ContentTinter), "controlChildContentTinters");
private static readonly FieldInfo DontTintColored = AccessTools.Field(typeof(ContentTinter), "dontTintColoredGraphics");
private static Color? configuredTint;
private static Color? appliedTint;
public static void Init(ConfigFile config)
{
Enabled = config.Bind<bool>("JudgesScales", "Enabled", true, "Pick the cards Judge's Scales discards all at once: a click marks a card where it sits in hand, and one Discard button discards every marked card and draws that many.");
selectedCardTint = config.Bind<string>("JudgesScales", "SelectedCardTint", "", "Colour of the cards picked for discard, as hex RRGGBB or RRGGBBAA (808080 is a mid grey). Empty: the grey the game uses for ineligible cards. A change applies at once, even while picking.");
config.SettingChanged += delegate(object _, SettingChangedEventArgs args)
{
if (args.ChangedSetting.Definition.Section == "JudgesScales")
{
Retint();
}
};
Retint();
}
internal static bool CannotDiscard(CardState card)
{
if (!card.HasTrait<CardTraitInfusion>())
{
return card.HasTrait<CardTraitPersistent>();
}
return true;
}
internal static bool IsSelected(CardUI cardUI)
{
if ((Object)(object)cardUI != (Object)null)
{
return Selected.Contains(cardUI.GetCardState());
}
return false;
}
internal static List<(int index, CardState card)> SelectedByHandIndexDescending()
{
List<(int, CardState)> list = new List<(int, CardState)>();
if ((Object)(object)Hand == (Object)null)
{
return list;
}
List<CardUI> cardUIList = Hand.GetCardUIList();
for (int num = cardUIList.Count - 1; num >= 0; num--)
{
if (IsSelected(cardUIList[num]))
{
list.Add((num, cardUIList[num].GetCardState()));
}
}
return list;
}
private static IEnumerable<CardUI> CardUIs()
{
if ((Object)(object)Hand == (Object)null)
{
yield break;
}
foreach (CardUI cardUI in Hand.GetCardUIList())
{
yield return cardUI;
}
object? value = FocusedCardUI.GetValue(Hand);
CardUI val = (CardUI)((value is CardUI) ? value : null);
if (val != null)
{
yield return val;
}
}
internal static void Reset()
{
UntintSelected();
Active = false;
Selected.Clear();
ConfirmButton = null;
Hand = null;
}
internal static void RefreshLook(CardUI cardUI)
{
CardState cardState = cardUI.GetCardState();
if (cardState != null && !CannotDiscard(cardState))
{
bool flag = Selected.Contains(cardState);
Tint(cardUI, flag);
if (flag)
{
cardUI.SetEdgeFxActive((EdgeHighlight)0, true);
}
}
}
internal static void RefreshAllLooks()
{
foreach (CardUI item in CardUIs())
{
RefreshLook(item);
}
}
internal static void RefreshButtons(GameUISelectableButton confirm, TMP_Text confirmLabel, GameUISelectableButton cancel)
{
int count = Selected.Count;
((Component)confirm).gameObject.SetActive(count > 0);
((Component)cancel).gameObject.SetActive(count == 0);
confirmLabel.text = LocalizationExtensions.Localize("ScreenDeck_Discard_Action", (ILocalizationParameterContext)null) + ((count > 1) ? $" ({count})" : string.Empty);
}
internal static void Retint()
{
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
string text = selectedCardTint?.Value?.Trim().TrimStart('#') ?? string.Empty;
Color? val = null;
if (text.Length > 0)
{
Color value = default(Color);
if (ColorUtility.TryParseHtmlString("#" + text, ref value))
{
val = value;
}
else
{
Plugin.Logger.LogWarning((object)("[Judge's Scales] SelectedCardTint '" + text + "' is not a hex colour; using the game's grey."));
}
}
configuredTint = val;
if (Active)
{
UntintSelected();
appliedTint = configuredTint;
RefreshAllLooks();
}
}
private static void UntintSelected()
{
foreach (CardUI item in CardUIs())
{
if (IsSelected(item))
{
Tint(item, on: false);
}
}
}
internal static void Tint(CardUI card, bool on)
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: 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_0061: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)card == (Object)null)
{
return;
}
object? value = CardFrontTinter.GetValue(card);
ContentTinter val = (ContentTinter)((value is ContentTinter) ? value : null);
if (val != null)
{
if (on)
{
appliedTint = configuredTint;
}
Color? val2 = appliedTint;
if (val2.HasValue)
{
Color valueOrDefault = val2.GetValueOrDefault();
Apply(val, on ? new Color?(valueOrDefault) : ((Color?)null), valueOrDefault);
}
else
{
val.Toggle(on);
}
}
}
private static void Apply(ContentTinter tinter, Color? colour, Color previous)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: 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_006a: 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_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: 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_017e: Unknown result type (might be due to invalid IL or missing references)
Color val = (Color)TintColor.GetValue(tinter);
bool flag = (bool)DontTintColored.GetValue(tinter);
foreach (Graphic item in (List<Graphic>)GraphicsToTint.GetValue(tinter))
{
if (!((Object)(object)item == (Object)null))
{
Color color = item.color;
if (!flag || color == Color.white || color == previous || color == val)
{
Color val2 = (Color)(((??)colour) ?? Color.white);
item.color = new Color(val2.r, val2.g, val2.b, color.a);
}
}
}
Color val3 = (Color)OverlayColor.GetValue(tinter);
foreach (Graphic item2 in (List<Graphic>)OverlaysToShow.GetValue(tinter))
{
if ((Object)(object)item2 != (Object)null)
{
item2.color = (colour.HasValue ? val3 : Color.clear);
}
}
if (!(bool)ControlChildTinters.GetValue(tinter))
{
return;
}
ContentTinter[] componentsInChildren = ((Component)tinter).GetComponentsInChildren<ContentTinter>();
foreach (ContentTinter val4 in componentsInChildren)
{
if ((Object)(object)val4 != (Object)(object)tinter)
{
Apply(val4, colour, previous);
}
}
}
internal static void KeepDiscardButtonSelected()
{
if (Active && Selected.Count != 0 && !((Object)(object)ConfirmButton == (Object)null) && ((Component)ConfirmButton).gameObject.activeInHierarchy)
{
InputManager inst = InputManager.Inst;
if (!((Object)(object)inst == (Object)null) && ((CoreInput)inst).currentInputModeUsesNavigation && !((Object)(object)EventSystem.current == (Object)null) && !((Object)(object)EventSystem.current.currentSelectedGameObject != (Object)null))
{
inst.SelectGameUIComponent((IGameUIComponent)(object)ConfirmButton, true, false);
}
}
}
}
[HarmonyPatch(typeof(RelicEffectChooseDiscardsDrawReplacementsOnPostOpeningDraw), "ApplyEffectOnPostOpeningDraw")]
internal static class JudgesScalesDiscardAtOncePatch
{
[CompilerGenerated]
private static class <>O
{
public static Action <0>__Reset;
public static CardStateChosenDelegate <1>__DiscardSelected;
public static CancelledDelegate <2>__KeepHand;
public static FilterCardStateDelegate <3>__CannotDiscard;
}
private static bool Prefix(ICoreGameManagers coreGameManagers, ref IEnumerator __result)
{
if (!JudgesScalesHandSelection.Enabled.Value)
{
return true;
}
AllGameManagers instance = AllGameManagers.Instance;
ReplayManager val = ((instance != null) ? instance.GetReplayManager() : null);
if (val != null && val.IsPlayingBackAReplay())
{
Plugin.Logger.LogDebug((object)"Judge's Scales: a replay is playing back, leaving the discard flow to the game.");
return true;
}
__result = Run(coreGameManagers);
return false;
}
private static IEnumerator Run(ICoreGameManagers coreGameManagers)
{
CardManager cardManager = coreGameManagers.GetCardManager();
AnimationTimingData animationTimingData = coreGameManagers.GetAllGameData().GetBalanceData().GetAnimationTimingData();
JudgesScalesHandSelection.Reset();
JudgesScalesHandSelection.Active = true;
cardManager.AddSelectCardFromHandOnCompletedCallback((Action)JudgesScalesHandSelection.Reset);
Params val = new Params
{
descriptionKey = "ScreenDeck_Select_CardEffectChooseDiscard",
overrideActionKey = "ScreenDeck_Discard_Action",
overrideCancelKey = "ScreenDeck_DiscardComplete_Action"
};
object obj = <>O.<1>__DiscardSelected;
if (obj == null)
{
CardStateChosenDelegate val2 = DiscardSelected;
<>O.<1>__DiscardSelected = val2;
obj = (object)val2;
}
val.cardChosenCallback = (CardStateChosenDelegate)obj;
object obj2 = <>O.<2>__KeepHand;
if (obj2 == null)
{
CancelledDelegate val3 = KeepHand;
<>O.<2>__KeepHand = val3;
obj2 = (object)val3;
}
val.cancelledCallback = (CancelledDelegate)obj2;
object obj3 = <>O.<3>__CannotDiscard;
if (obj3 == null)
{
FilterCardStateDelegate val4 = JudgesScalesHandSelection.CannotDiscard;
<>O.<3>__CannotDiscard = val4;
obj3 = (object)val4;
}
val.filterCallback = (FilterCardStateDelegate)obj3;
val.instantApplyDelay = animationTimingData.cardDrawAnimationDuration;
val.disableIneligibleCards = true;
val.allowShowCancel = true;
val.selectionHandState = (CardUIState)9;
yield return cardManager.SelectCardFromHand(val, false);
}
private static IEnumerator DiscardSelected(CardState chosenCard, CardManager cardManager)
{
List<(int index, CardState card)> cards = JudgesScalesHandSelection.SelectedByHandIndexDescending();
JudgesScalesHandSelection.Reset();
if (cards.Count == 0)
{
yield break;
}
AllGameManagers instance = AllGameManagers.Instance;
ReplayManager replay = ((instance != null) ? instance.GetReplayManager() : null);
for (int i = 0; i < cards.Count; i++)
{
var (num, discardCard) = cards[i];
if (i > 0)
{
if (replay != null)
{
replay.RecordEntry((ReplayEntry)new ReplayEntryHandSelectionCard(num));
}
}
yield return cardManager.DiscardCard(new DiscardCardParams
{
discardCard = discardCard,
triggeredByCard = true,
wasPlayed = false
}, false);
cardManager.RefreshHandCards(true, false);
}
if (cardManager.GetHand(false).Any((CardState card) => !JudgesScalesHandSelection.CannotDiscard(card)))
{
if (replay != null)
{
replay.RecordEntry((ReplayEntry)new ReplayEntryHandSelectionDone());
}
}
cardManager.DrawCards(cards.Count, (CardState)null, (CardType)4, -1);
}
private static IEnumerator KeepHand(CardManager cardManager)
{
JudgesScalesHandSelection.Reset();
yield break;
}
}
[HarmonyPatch(typeof(HandUI), "ReplayHandSelection")]
internal static class JudgesScalesReplayHandSelectionPatch
{
private const float ConfirmTimeoutSeconds = 2f;
private static bool Prefix(int cardIndex, ref IEnumerator __result, HandUI __instance, HandSelectionUI ___handSelectionUI, List<CardUI> ___cardUIs)
{
__result = Replay(cardIndex, __instance, ___handSelectionUI, ___cardUIs);
return false;
}
private static IEnumerator Replay(int cardIndex, HandUI handUI, HandSelectionUI handSelectionUI, List<CardUI> cardUIs)
{
if (!handUI.IsHandSelectionActive() || cardIndex < 0 || cardIndex >= cardUIs.Count)
{
Plugin.Logger.LogDebug((object)$"Replay of hand selection card {cardIndex}: overlay active {handUI.IsHandSelectionActive()}, {cardUIs.Count} cards in hand; nothing to do.");
yield break;
}
bool flag = handSelectionUI.SelectCard(cardUIs[cardIndex]);
Plugin.Logger.LogDebug((object)$"Replay of hand selection card {cardIndex}: SelectCard returned {flag}.");
if (!flag)
{
yield break;
}
yield return null;
float started = Time.unscaledTime;
while (Time.unscaledTime - started < 2f)
{
if (ReplayManager.TryClickButton((MonoBehaviour)(object)handSelectionUI.GetConfirmButton()))
{
Plugin.Logger.LogDebug((object)$"Replay of hand selection card {cardIndex}: confirmed after {Time.unscaledTime - started:f2}s.");
yield break;
}
yield return null;
}
Plugin.Logger.LogWarning((object)$"Replay of hand selection card {cardIndex}: the confirm button never became clickable.");
}
}
[HarmonyPatch(typeof(HandSelectionUI), "SelectCard")]
internal static class JudgesScalesToggleCardPatch
{
private static bool Prefix(CardUI cardUI, ref bool __result, HandUI ___handUI, GameUISelectableButton ___confirmButton, TMP_Text ___confirmButtonLabel, GameUISelectableButton ___cancelButton)
{
if (!JudgesScalesHandSelection.Active)
{
return true;
}
JudgesScalesHandSelection.ConfirmButton = ___confirmButton;
JudgesScalesHandSelection.Hand = ___handUI;
CardState cardState = cardUI.GetCardState();
List<CardState> selected = JudgesScalesHandSelection.Selected;
if (!selected.Remove(cardState))
{
selected.Add(cardState);
if (((CoreInput)InputManager.Inst).currentInputModeUsesNavigation)
{
InputManager.Inst.SelectGameUIComponent((IGameUIComponent)(object)___confirmButton, true, false);
}
}
JudgesScalesHandSelection.RefreshAllLooks();
JudgesScalesHandSelection.RefreshButtons(___confirmButton, ___confirmButtonLabel, ___cancelButton);
__result = false;
return false;
}
}
[HarmonyPatch(typeof(HandSelectionUI), "UnSelectCard")]
internal static class JudgesScalesUnselectAllPatch
{
private static void Prefix(GameUISelectableButton ___confirmButton, TMP_Text ___confirmButtonLabel, GameUISelectableButton ___cancelButton)
{
if (JudgesScalesHandSelection.Active && JudgesScalesHandSelection.Selected.Count != 0)
{
JudgesScalesHandSelection.Selected.Clear();
JudgesScalesHandSelection.RefreshAllLooks();
JudgesScalesHandSelection.RefreshButtons(___confirmButton, ___confirmButtonLabel, ___cancelButton);
}
}
}
[HarmonyPatch(typeof(HandSelectionUI), "Finish")]
internal static class JudgesScalesFinishPatch
{
private static void Prefix(ref CardUI ___currentlySelectedCardUI, HandUI ___handUI)
{
if (JudgesScalesHandSelection.Active && JudgesScalesHandSelection.Selected.Count != 0)
{
___currentlySelectedCardUI = ((IEnumerable<CardUI>)___handUI.GetCardUIList()).LastOrDefault((Func<CardUI, bool>)JudgesScalesHandSelection.IsSelected);
}
}
}
[HarmonyPatch(typeof(HandUI), "UpdateCardUIAtEndOfFrame")]
internal static class JudgesScalesCardLookPatch
{
private static void Postfix(CardUI cardUI)
{
if (JudgesScalesHandSelection.Active)
{
JudgesScalesHandSelection.RefreshLook(cardUI);
}
}
}
}
namespace UITweaks.InscryptionWarning
{
internal sealed class SharedNodeMarker : MonoBehaviour
{
}
internal static class MapHintPatch
{
internal enum CueColor
{
Gold,
Red,
Blue
}
internal enum CueStyle
{
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.LogDebug((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);
}
}
internal const string Section = "InscryptionWarning";
private const string OverlayName = "UITweaks_InscryptionHint";
private const int GlowTextureSize = 128;
private const float GlowCoreRadius = 0.2f;
private const float DiegeticHaloScale = 1.5f;
private static ConfigEntry<bool> enabled = null;
private static ConfigEntry<CueStyle> style = 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 int loggedPlanFor = int.MinValue;
public static void Init(ConfigFile config)
{
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Expected O, but got Unknown
enabled = config.Bind<bool>("InscryptionWarning", "Enabled", true, "Highlight on the map the branch the Inscryption event's secret code asks for, at each of its three choices.");
style = config.Bind<CueStyle>("InscryptionWarning", "CueStyle", CueStyle.Diegetic, "How obvious the hint is: 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>("InscryptionWarning", "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>("InscryptionWarning", "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>("InscryptionWarning", "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.");
config.SettingChanged += delegate(object _, SettingChangedEventArgs args)
{
if (args.ChangedSetting.Definition.Section == "InscryptionWarning")
{
RefreshLiveOverlays();
}
};
EventStartLocator.LogAvailability();
SelfCheck();
Plugin.Logger.LogDebug((object)($"MapHintPatch ready: Enabled={enabled.Value}, CueStyle={style.Value}, CueColor={cueColor.Value}, " + $"DiegeticStrength={diegeticStrength.Value}, VerboseLogging={verboseLogging.Value}"));
}
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("UITweaks_InscryptionHint");
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.LogDebug((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 (!enabled.Value || (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("UITweaks_InscryptionHint");
if ((Object)(object)val != (Object)null)
{
return ((Component)val).gameObject;
}
GameObject val2 = new GameObject("UITweaks_InscryptionHint", 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 = "UITweaks_InscryptionHint_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;
}
}
}
}
}
namespace UITweaks.GreedBlights
{
internal static class GreedBlightAura
{
[HarmonyPatch(typeof(CardUI), "SetEdgeFxActive")]
private static class GoldEdge
{
private static void Postfix(CardUI __instance)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Invalid comparison between Unknown and I4
if (Enabled.Value && !(ChampionEdge == null) && (int)__instance.GetUIState() == 1 && DamagesPyre(__instance.GetCardState()) && GreedActive())
{
object? value = ChampionEdge.GetValue(__instance);
Transform val = (Transform)((value is Transform) ? value : null);
if (val != null)
{
((Component)val).gameObject.SetActive(true);
}
}
}
}
internal const string Section = "GreedBlights";
internal static ConfigEntry<bool> Enabled = null;
private static readonly FieldInfo ChampionEdge = AccessTools.Field(typeof(CardUI), "_championEdgeFXTransform");
private static int checkedFrame = -1;
private static bool greedActive;
public static void Init(ConfigFile config)
{
Enabled = config.Bind<bool>("GreedBlights", "Enabled", true, "With Fhyra's Greed (or any relic paying gold when the Pyre takes damage), give the Blights in hand that damage the Pyre a gold glow.");
if (ChampionEdge == null)
{
Plugin.Logger.LogError((object)"CardUI._championEdgeFXTransform is gone; no Blight will glow.");
}
}
private static bool GreedActive()
{
if (checkedFrame == Time.frameCount)
{
return greedActive;
}
checkedFrame = Time.frameCount;
AllGameManagers instance = AllGameManagers.Instance;
SaveManager val = ((instance != null) ? instance.GetSaveManager() : null);
greedActive = (Object)(object)val != (Object)null && val.GetAllRelics().Any((RelicState relic) => relic.HasEffectOfType<RelicEffectAddGoldOnPyreDamage>());
return greedActive;
}
internal static bool DamagesPyre(CardState? card)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Invalid comparison between Unknown and I4
if (card == null || (int)card.GetCardType() != 5)
{
return false;
}
if (card.GetEffectStates().Any(DamagesPyre))
{
return true;
}
foreach (CardTriggerEffectState trigger in card.GetTriggers())
{
if (trigger.GetCardEffectParams().Any(DamagesPyre))
{
return true;
}
}
return false;
}
private static bool DamagesPyre(CardEffectState effect)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Invalid comparison between Unknown and I4
if (effect.GetCardEffect() is CardEffectDamage)
{
return (int)effect.GetTargetMode() == 21;
}
return false;
}
}
}
namespace UITweaks.ForgeSmartToggle
{
internal enum ToggleOrder
{
NormalHybridDisabled,
NormalDisabledHybrid
}
internal static class HybridForgePatch
{
[HarmonyPatch(typeof(SaveManager), "ToggleForgeActive")]
private static class Cycle
{
private static bool nextHybrid;
private static bool Prefix(SaveManager __instance)
{
if (!enabled.Value)
{
nextHybrid = false;
return true;
}
(bool hybrid, bool flip) tuple = NextState(__instance.IsForgeToggleActive(), hybrid, toggleOrder.Value);
bool item = tuple.hybrid;
bool item2 = tuple.flip;
nextHybrid = item;
return item2;
}
private static void Postfix()
{
hybrid = nextHybrid;
}
}
[HarmonyPatch(typeof(SaveManager), "SetForgeToggleActive")]
private static class ClearOnDirectSet
{
private static void Prefix(SaveManager __instance, bool isActive)
{
if (__instance.IsForgeToggleActive() != isActive)
{
hybrid = false;
}
}
}
[HarmonyPatch(typeof(PlayerManager), "OnCardPlayedPreEffectsFired")]
private static class SkipForgeOnPlay
{
private static bool Prefix(CardState cardState, bool fromDirectPlay, ref IEnumerator __result)
{
if (!hybrid || !fromDirectPlay || cardState == null || !IsSkipped(cardState))
{
return true;
}
Plugin.Logger.LogDebug((object)("Hybrid forge: skipping '" + cardState.GetTitle() + "'"));
__result = Nothing();
return false;
}
private static IEnumerator Nothing()
{
yield break;
}
}
[HarmonyPatch(typeof(ForgePointsUI), "SetStateForgingActive")]
private static class MarkToggle
{
private static void Postfix(ForgePointsUI __instance)
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: 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_0056: 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_006e: Unknown result type (might be due to invalid IL or missing references)
GameObject value = Traverse.Create((object)__instance).Field<GameObject>("forgingActiveToggle").Value;
if ((Object)(object)value == (Object)null)
{
return;
}
RefreshBadge(__instance, value);
Graphic componentInChildren = value.GetComponentInChildren<Graphic>(true);
if ((Object)(object)componentInChildren != (Object)null)
{
Color valueOrDefault = originalTint.GetValueOrDefault();
if (!originalTint.HasValue)
{
valueOrDefault = componentInChildren.color;
originalTint = valueOrDefault;
}
componentInChildren.color = (hybrid ? HybridTint : originalTint.Value);
}
Traverse.Create((object)__instance).Method("RefreshTooltip", Array.Empty<object>()).GetValue();
}
}
[HarmonyPatch(typeof(ForgePointsUI), "SetTooltip")]
private static class TooltipNote
{
private static void Prefix(ref string title, ref string body)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
if (hybrid)
{
title += " (Hybrid)";
string text = SkippedList();
string text2 = ColorUtility.ToHtmlStringRGB(HybridTint);
body += ((text.Length > 0) ? ("\n\n<b>Hybrid forging</b> (<color=#" + text2 + ">H</color> on the button): Forge Points are spent as usual, except on these units and cards, which are ignored:\n<color=#" + text2 + ">" + text + "</color>") : "\n\n<b>Hybrid forging</b>: nothing is ignored - both ignore lists in the [ForgeSmartToggle] section of BepInEx/config/SpecialCircumstances.UITweaks.cfg are empty.");
}
}
}
internal const string Section = "ForgeSmartToggle";
private static ConfigEntry<bool> enabled = null;
private static ConfigEntry<ToggleOrder> toggleOrder = null;
private static ConfigEntry<string> skippedSubtypes = null;
private static ConfigEntry<string> skippedCards = null;
private static bool hybrid;
private static Color? originalTint;
private static TextMeshProUGUI? hybridBadge;
private static readonly Color HybridTint = new Color(1f, 0.69f, 0.13f);
public static void Init(ConfigFile config)
{
enabled = config.Bind<bool>("ForgeSmartToggle", "Enabled", true, "Enable the Hybrid forge state. When disabled, the toggle stays plain Off -> On -> Off.");
toggleOrder = config.Bind<ToggleOrder>("ForgeSmartToggle", "ToggleOrder", ToggleOrder.NormalDisabledHybrid, "Order the forge toggle cycles the three states in.\nNormalHybridDisabled: Normal -> Hybrid -> Disabled -> Normal (one press from Disabled turns forging on as Normal).\nNormalDisabledHybrid: Normal -> Disabled -> Hybrid -> Normal (one press turns forging off again from Normal, and the press after that enters Hybrid).");
skippedSubtypes = config.Bind<string>("ForgeSmartToggle", "SkippedSubtypes", "Morsel, Imp, Whelp, Steward", "Comma-separated unit subtypes that do NOT consume Forge Points while the forge toggle is in its Hybrid state. Matched case-insensitively as a substring of both the subtype key and its localized name.");
skippedCards = config.Bind<string>("ForgeSmartToggle", "SkippedCards", "CraftedEquipment", "Comma-separated cards (units or equipment) that do NOT consume Forge Points while the forge toggle is in its Hybrid state. Matched case-insensitively as a substring of both the card's asset name (e.g. CraftedEquipment) and its localized title.");
SelfCheck();
}
internal static bool Matches(string subtypeKey, string localizedName, string configuredList)
{
string[] array = configuredList.Split(',');
for (int i = 0; i < array.Length; i++)
{
string text = array[i].Trim();
if (text.Length != 0 && (subtypeKey.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0 || localizedName.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0))
{
return true;
}
}
return false;
}
internal static (bool hybrid, bool flip) NextState(bool active, bool inHybrid, ToggleOrder order)
{
if (order == ToggleOrder.NormalDisabledHybrid)
{
if (!(active && inHybrid))
{
return (hybrid: !active, flip: true);
}
return (hybrid: false, flip: false);
}
if (!active || inHybrid)
{
return (hybrid: false, flip: true);
}
return (hybrid: true, flip: false);
}
private static void SelfCheck()
{
if (!Matches("SubtypeData_Morsel", "Morsel", "Morsel, Imp, Whelp") || !Matches("SubtypeData_Imp", "Imp", "Morsel, Imp, Whelp") || !Matches("whatever", "Whelp", "Morsel, Imp, Whelp") || Matches("SubtypeData_Dragon", "Dragon", "Morsel, Imp, Whelp") || Matches("SubtypeData_Imp", "Imp", " , ") || !Matches("CraftedEquipment", "Crafted Equipment", "CraftedEquipment"))
{
throw new InvalidOperationException("HybridForgePatch.Matches self-check failed");
}
CycleSelfCheck(ToggleOrder.NormalHybridDisabled, (true, false), (true, true), (false, false), (true, false));
CycleSelfCheck(ToggleOrder.NormalDisabledHybrid, (true, true), (true, false), (false, false), (true, true));
}
private static void CycleSelfCheck(ToggleOrder order, params (bool active, bool hybrid)[] presses)
{
bool flag = false;
bool flag2 = false;
for (int i = 0; i < presses.Length; i++)
{
(bool, bool) tuple = presses[i];
(bool hybrid, bool flip) tuple2 = NextState(flag, flag2, order);
bool item = tuple2.hybrid;
bool item2 = tuple2.flip;
flag ^= item2;
flag2 = item;
if (flag != tuple.Item1 || flag2 != tuple.Item2)
{
throw new InvalidOperationException($"HybridForgePatch.NextState self-check failed for {order}");
}
}
}
private static bool IsSkipped(CardState card)
{
if (Matches(card.GetAssetName() ?? string.Empty, card.GetTitle() ?? string.Empty, skippedCards.Value))
{
return true;
}
CharacterData spawnCharacterData = card.GetSpawnCharacterData();
List<SubtypeData> list = ((spawnCharacterData != null) ? spawnCharacterData.GetSubtypes() : null);
if (list == null)
{
return false;
}
foreach (SubtypeData item in list)
{
if (Matches(item.Key ?? string.Empty, item.LocalizedName ?? string.Empty, skippedSubtypes.Value))
{
return true;
}
}
return false;
}
private static string SkippedList()
{
IEnumerable<string> values = from entry in (skippedSubtypes.Value + "," + skippedCards.Value).Split(',')
select entry.Trim() into entry
where entry.Length > 0
select entry;
return string.Join(", ", values);
}
private static void RefreshBadge(ForgePointsUI ui, GameObject toggle)
{
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)hybridBadge == (Object)null)
{
TextMeshProUGUI value = Traverse.Create((object)ui).Field<TextMeshProUGUI>("countLabel").Value;
if ((Object)(object)value == (Object)null)
{
return;
}
hybridBadge = Object.Instantiate<TextMeshProUGUI>(value, toggle.transform);
((Object)hybridBadge).name = "HybridBadge";
((TMP_Text)hybridBadge).text = "H";
((TMP_Text)hybridBadge).fontSize = ((TMP_Text)value).fontSize * 0.65f;
((Graphic)hybridBadge).color = HybridTint;
((TMP_Text)hybridBadge).alignment = (TextAlignmentOptions)514;
((Graphic)hybridBadge).raycastTarget = false;
RectTransform rectTransform = ((TMP_Text)hybridBadge).rectTransform;
Vector2 val = default(Vector2);
((Vector2)(ref val))..ctor(1f, 0f);
rectTransform.anchorMax = val;
rectTransform.anchorMin = val;
rectTransform.pivot = new Vector2(0.5f, 0.5f);
rectTransform.anchoredPosition = Vector2.zero;
rectTransform.sizeDelta = new Vector2(28f, 28f);
((Transform)rectTransform).localScale = Vector3.one;
}
((Component)hybridBadge).gameObject.SetActive(hybrid);
}
}
}
namespace UITweaks.DeckColumns
{
internal static class DeckColumns
{
[HarmonyPatch(typeof(DeckScreen), "RefreshMode")]
private static class ColumnCount
{
private static void Postfix(Mode ___mode, GridLayoutGroup ___cardGrid)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
if (Applies(___mode))
{
___cardGrid.constraintCount = columns.Value;
}
}
}
[HarmonyPatch(typeof(DeckScreen), "UpdateCardTooltipSides")]
private static class TooltipSides
{
private static void Postfix(DeckScreen __instance, Mode ___mode)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
if (!Applies(___mode) || CardInfos == null || !(CardInfos.GetValue(__instance) is List<CardInfo> list))
{
return;
}
int value = columns.Value;
for (int i = 0; i < list.Count; i++)
{
CardUI cardUI = list[i].cardUI;
if ((Object)(object)cardUI != (Object)null)
{
cardUI.SetTooltipSide((TooltipSide)((i % value == value - 1) ? 3 : 4));
}
}
}
}
internal const string Section = "DeckColumns";
private const int VanillaColumns = 4;
internal static ConfigEntry<bool> Enabled = null;
private static ConfigEntry<int> columns = null;
private static readonly FieldInfo CardInfos = AccessTools.Field(typeof(DeckScreen), "cardInfos");
public static void Init(ConfigFile config)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Expected O, but got Unknown
Enabled = config.Bind<bool>("DeckColumns", "Enabled", true, "Lay the deck screen's cards out in more columns than the game's 4.");
columns = config.Bind<int>("DeckColumns", "Columns", 6, new ConfigDescription("How many columns of cards the deck screen shows. 6 full-size cards fill 1730 of the screen's 1920 units; 7 overflow it.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 8), Array.Empty<object>()));
if (CardInfos == null)
{
Plugin.Logger.LogError((object)"DeckScreen.cardInfos is gone; tooltip sides will stay the game's.");
}
}
private static bool Applies(Mode mode)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Invalid comparison between Unknown and I4
if (Enabled.Value && columns.Value != 4)
{
return (int)mode != 10;
}
return false;
}
}
}