using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DiskCardGame;
using HarmonyLib;
using InscryptionAPI.Card;
using Pixelplacement;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("InscryptionAPI")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization")]
[assembly: AssemblyCompany("UnlimitedInscryption")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Do everything as much as you want")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+6f3eb15306b25a9c4765e0307e6e0705d6b3278a")]
[assembly: AssemblyProduct("UnlimitedInscryption")]
[assembly: AssemblyTitle("UnlimitedInscryption")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace UnlimitedInscryption
{
public static class Configs
{
public static bool DuplicateMergeOverrideEnabled = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Mycologist", "Enabled", true, new ConfigDescription("Enables the mods new behaviour to change how the Mycologist works when combining Duplicates when True", (AcceptableValueBase)null, Array.Empty<object>())).Value;
public static bool CardRemoveOverrideEnabled = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Bone Lord", "Enabled", true, new ConfigDescription("Enables the mods new behaviour to change how the Bone Lord works when True", (AcceptableValueBase)null, Array.Empty<object>())).Value;
public static bool CardMergeOverrideEnabled = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Card Merge", "Enabled", true, new ConfigDescription("Enables the mods new behaviour to change how the Card Merging map node works when True", (AcceptableValueBase)null, Array.Empty<object>())).Value;
public static bool CardMergeAllowMultipleSigilTransfers = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Card Merge", "Allow Multiple Merges", true, new ConfigDescription("Screw restrictions of what can merge into what. Anything goes!", (AcceptableValueBase)null, Array.Empty<object>())).Value;
public static bool TotemOverrideEnabled = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Wood Carver", "Enabled", true, new ConfigDescription("Enables the mods new behaviour to change how the Wood Carver selection works when True", (AcceptableValueBase)null, Array.Empty<object>())).Value;
public static bool TotemIncludeUnlearnedAbilities = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Wood Carver", "Unlearned Abilities", true, new ConfigDescription("Include unlearned abilities as totem bottoms", (AcceptableValueBase)null, Array.Empty<object>())).Value;
public static bool TotemIncludeOverpoweredAbilities = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Wood Carver", "Overpowered Abilities", true, new ConfigDescription("Include abilities with a power level higher than normal", (AcceptableValueBase)null, Array.Empty<object>())).Value;
public static bool TotemIncludeNonAct1Abilities = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Wood Carver", "Include Non Act1 Abilities", false, new ConfigDescription("Include all abilities not from Act1", (AcceptableValueBase)null, Array.Empty<object>())).Value;
public static bool FlameOverrideEnabled = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Flame", "Enabled", true, new ConfigDescription("Enables the mods new behaviour to change how the Flame works when True", (AcceptableValueBase)null, Array.Empty<object>())).Value;
public static bool CopyCardOverrideEnabled = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Goobert", "Enabled", true, new ConfigDescription("Offers Repeat and Exit after each painting so Goobert can copy more cards during the same visit.", (AcceptableValueBase)null, Array.Empty<object>())).Value;
public static float FlameDestroyCardChance = Mathf.Clamp(((BaseUnityPlugin)Plugin.Instance).Config.Bind<float>("Flame", "Destroy Chance", 22.5f, new ConfigDescription("Chance to destroy the selected card on every buff attempt, including the first. Default = 22.5%. 0 = never destroys. 100 = always destroys", (AcceptableValueBase)null, Array.Empty<object>())).Value, 0f, 100f);
public static void Init()
{
}
}
[BepInPlugin("jamesgames.inscryption.unlimitedinscryption", "Unlimited Inscryption", "1.0.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
public const string PluginGuid = "jamesgames.inscryption.unlimitedinscryption";
public const string PluginName = "Unlimited Inscryption";
public const string PluginVersion = "1.0.1";
public static string PluginDirectory;
public static ManualLogSource Log;
public static Plugin Instance;
public bool FuckSacrificeRestrictionsInstalled { get; private set; }
public bool FirePitAlwaysAbleToUpgradeInstalled { get; private set; }
private void Awake()
{
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
Instance = this;
((BaseUnityPlugin)this).Logger.LogInfo((object)"Loading Unlimited Inscryption...");
PluginDirectory = ((BaseUnityPlugin)this).Info.Location.Replace("UnlimitedInscryption.dll", "");
Harmony val = new Harmony("jamesgames.inscryption.unlimitedinscryption");
val.PatchAll();
Configs.Init();
((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded Unlimited Inscryption!");
}
}
public static class Utils
{
public static Texture2D GetTextureFromPath(string path)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected O, but got Unknown
byte[] array = File.ReadAllBytes(Path.Combine(Plugin.PluginDirectory, path));
Texture2D val = new Texture2D(2, 2);
ImageConversion.LoadImage(val, array);
return val;
}
public static void PrintHierarchy(GameObject go, bool printParents)
{
string text = "";
if (printParents)
{
List<Transform> list = new List<Transform>();
Transform parent = go.transform.parent;
while ((Object)(object)parent != (Object)null)
{
list.Add(parent);
parent = parent.parent;
}
for (int num = list.Count - 1; num >= 0; num--)
{
Transform val = list[num];
string text2 = text + ((Object)((Component)val).gameObject).name + "(" + ((Object)((Component)val).gameObject).GetInstanceID() + ")";
Plugin.Log.LogInfo((object)(text + text2));
text += "\t";
}
}
PrintGameObject(go, text);
}
private static void PrintGameObject(GameObject go, string prefix = "")
{
string text = ((Object)go).name + "(" + ((Object)go).GetInstanceID() + ")";
Plugin.Log.LogInfo((object)(prefix + text));
Plugin.Log.LogInfo((object)(prefix + "- Components: " + go.transform.childCount));
Component[] components = go.GetComponents<Component>();
foreach (Component val in components)
{
Plugin.Log.LogInfo((object)(prefix + "-- " + ((object)val).GetType()));
SpriteRenderer val2 = (SpriteRenderer)(object)((val is SpriteRenderer) ? val : null);
if (val2 != null)
{
Plugin.Log.LogInfo((object)(prefix + "-- Name: " + ((Object)val2).name));
Plugin.Log.LogInfo((object)(prefix + "-- Sprite Name: " + (((Object)(object)val2.sprite != (Object)null) ? ((Object)val2.sprite).name : "null")));
}
}
Plugin.Log.LogInfo((object)(prefix + "- Children: " + go.transform.childCount));
for (int j = 0; j < go.transform.childCount; j++)
{
PrintGameObject(((Component)go.transform.GetChild(j)).gameObject, prefix + "\t");
}
}
public static T GetPrivatePropertyValue<T>(this object obj, string propName)
{
if (obj == null)
{
throw new ArgumentNullException("obj");
}
PropertyInfo property = obj.GetType().GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (property == null)
{
throw new ArgumentOutOfRangeException("propName", $"Property {propName} was not found in Type {obj.GetType().FullName}");
}
return (T)property.GetValue(obj, null);
}
public static T GetPrivateFieldValue<T>(this object obj, string propName)
{
if (obj == null)
{
throw new ArgumentNullException("obj");
}
Type type = obj.GetType();
FieldInfo fieldInfo = null;
while (fieldInfo == null && type != null)
{
fieldInfo = type.GetField(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
type = type.BaseType;
}
if (fieldInfo == null)
{
throw new ArgumentOutOfRangeException("propName", $"Field {propName} was not found in Type {obj.GetType().FullName}");
}
return (T)fieldInfo.GetValue(obj);
}
public static void SetPrivatePropertyValue<T>(this object obj, string propName, T val)
{
Type type = obj.GetType();
if (type.GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) == null)
{
throw new ArgumentOutOfRangeException("propName", $"Property {propName} was not found in Type {obj.GetType().FullName}");
}
type.InvokeMember(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty, null, obj, new object[1] { val });
}
public static void SetPrivateFieldValue<T>(this object obj, string propName, T val)
{
if (obj == null)
{
throw new ArgumentNullException("obj");
}
Type type = obj.GetType();
FieldInfo fieldInfo = null;
while (fieldInfo == null && type != null)
{
fieldInfo = type.GetField(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
type = type.BaseType;
}
if (fieldInfo == null)
{
throw new ArgumentOutOfRangeException("propName", $"Field {propName} was not found in Type {obj.GetType().FullName}");
}
fieldInfo.SetValue(obj, val);
}
}
}
namespace UnlimitedInscryption.Scripts.Patches
{
[HarmonyPatch(typeof(BuildTotemSequencer), "Start", new Type[] { })]
public class BuildTotemSequencer_Start
{
public static void Postfix(BuildTotemSequencer __instance)
{
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: 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_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_0157: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: 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_0167: Expected O, but got Unknown
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: Unknown result type (might be due to invalid IL or missing references)
//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
//IL_01ae: Expected O, but got Unknown
if (!Configs.TotemOverrideEnabled)
{
return;
}
List<SelectableItemSlot> inventorySlots = __instance.inventorySlots;
int count = inventorySlots.Count;
for (int i = 0; i < count; i++)
{
SelectableItemSlot val = __instance.inventorySlots[i];
SelectableItemSlot val2 = Object.Instantiate<SelectableItemSlot>(val, ((Component)val).transform.parent);
Vector3 localPosition = ((Component)val2).transform.localPosition;
localPosition.y += 1.5f;
((Component)val2).transform.localPosition = localPosition;
inventorySlots.Add(val2);
}
for (int j = 0; j < count; j++)
{
SelectableItemSlot val3 = __instance.inventorySlots[j];
SelectableItemSlot val4 = Object.Instantiate<SelectableItemSlot>(val3, ((Component)val3).transform.parent);
Vector3 localPosition2 = ((Component)val4).transform.localPosition;
localPosition2.y += 3f;
((Component)val4).transform.localPosition = localPosition2;
inventorySlots.Add(val4);
}
Plugin.Log.LogInfo((object)("[BuildTotemSequencer_Start] slots: " + __instance.inventorySlots.Count));
List<ItemData> list = new List<ItemData>();
List<ItemData> list2 = new List<ItemData>();
foreach (Tribe totemTop in RunState.Run.totemTops)
{
list.Add((ItemData)new TotemTopData(totemTop));
}
foreach (Ability totemBottom in RunState.Run.totemBottoms)
{
list2.Add((ItemData)new TotemBottomData(totemBottom));
}
List<ItemData> list3 = TotemsUtil.AlternateTopsAndBottoms(list, list2);
Plugin.Log.LogInfo((object)("[BuildTotemSequencer_Start] inventory: " + list3.Count));
}
}
[HarmonyPatch(typeof(BuildTotemSequencer), "NewPiecePhase", new Type[] { typeof(BuildTotemNodeData) })]
public class BuildTotemSequencer_NewPiecePhase
{
public static bool Prefix(BuildTotemSequencer __instance, BuildTotemNodeData nodeData, ref IEnumerator __result)
{
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
if (!Configs.TotemOverrideEnabled)
{
return true;
}
Transform val = ((Component)__instance).transform.Find("CustomSelectButton");
if ((Object)(object)val == (Object)null)
{
val = GameObject.Find("ConfirmStoneButton").transform;
GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, val.parent);
((Object)val2).name = "CustomSelectButton";
((Component)val2.transform.GetChild(0)).gameObject.SetActive(true);
val2.transform.localPosition = new Vector3(0f, 5f, -3.9f);
Transform child = val2.transform.GetChild(0).GetChild(0).GetChild(0)
.GetChild(0);
MeshRenderer component = ((Component)child).GetComponent<MeshRenderer>();
Material[] materials = ((Renderer)component).materials;
materials[0].mainTexture = (Texture)(object)Utils.GetTextureFromPath("Artwork/close_button.png");
((Renderer)component).materials = materials;
val = val2.transform;
ConfirmStoneButton componentInChildren = ((Component)val).GetComponentInChildren<ConfirmStoneButton>(true);
componentInChildren.SetPrivateFieldValue<View>("confirmView", (View)1);
}
ConfirmStoneButton componentInChildren2 = ((Component)val).GetComponentInChildren<ConfirmStoneButton>(true);
((Component)((Component)componentInChildren2).transform.parent.parent).gameObject.SetActive(true);
__result = Sequence(__instance, nodeData, componentInChildren2);
return false;
}
private static IEnumerator Sequence(BuildTotemSequencer __instance, BuildTotemNodeData nodeData, ConfirmStoneButton selectButton)
{
Singleton<ViewManager>.Instance.Controller.SwitchToControlMode((ControlMode)17, false);
int seed = SaveManager.SaveFile.GetCurrentRandomSeed();
List<ItemData> totemChoices = __instance.GenerateTotemChoices(nodeData, seed);
yield return (object)new WaitForSeconds(0.25f);
List<bool> finishedSlots = new List<bool> { false, false };
for (int i = 0; i < ((SelectItemsSequencer)__instance).slots.Count; i++)
{
if (totemChoices.Count <= 0)
{
break;
}
__instance.CreatePieceInSlot(totemChoices[0], ((SelectItemsSequencer)__instance).slots[i]);
InitializeSlot(__instance, totemChoices[0], ((SelectItemsSequencer)__instance).slots[i], ClickTotemPieceCallback);
totemChoices.RemoveAt(0);
yield return (object)new WaitForSeconds(0.1f);
}
yield return (object)new WaitForSeconds(0.5f);
((SelectItemsSequencer)__instance).SetSlotCollidersEnabled(true);
selectButton.Enter();
Coroutine coroutine = ((MonoBehaviour)__instance).StartCoroutine(WaitForSelectButton(selectButton, finishedSlots));
yield return (object)new WaitUntil((Func<bool>)(() => finishedSlots[0] || finishedSlots[1]));
if (finishedSlots[0])
{
yield return Singleton<TextDisplayer>.Instance.PlayDialogueEvent("WoodcarverMaxPieces", (MessageAdvanceMode)1, (EventIntersectMode)0, (string[])null, (Action<Line>)null);
}
selectButton.Exit();
if (coroutine != null)
{
((MonoBehaviour)__instance).StopCoroutine(coroutine);
}
Singleton<RuleBookController>.Instance.SetShown(false, true);
Singleton<ViewManager>.Instance.Controller.LockState = (ViewLockState)1;
((SelectItemsSequencer)__instance).DisableSlotsAndExitItems((SelectableItemSlot)null);
Singleton<OpponentAnimationController>.Instance.ClearLookTarget();
yield return (object)new WaitForSeconds(0.2f);
yield return (object)new WaitForSeconds(0.15f);
((SelectItemsSequencer)__instance).SetSlotsActive(false);
void ClickTotemPieceCallback(MainInputInteractable val2)
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
SelectableItemSlot val = (SelectableItemSlot)(object)((val2 is SelectableItemSlot) ? val2 : null);
Item item = ((ItemSlot)val).Item;
if (item.Data is TotemTopData)
{
List<Tribe> totemTops = RunState.Run.totemTops;
ItemData data = item.Data;
totemTops.Add(((TotemTopData)((data is TotemTopData) ? data : null)).prerequisites.tribe);
}
else
{
List<Ability> totemBottoms = RunState.Run.totemBottoms;
ItemData data2 = item.Data;
totemBottoms.Add(((TotemBottomData)((data2 is TotemBottomData) ? data2 : null)).effectParams.ability);
}
item.PlayExitAnimation();
item.ShowHighlighted(false, false);
__instance.CreatePieceInSlot(item.Data, __instance.GetFirstEmptyInventorySlot());
if ((Object)(object)__instance.GetFirstEmptyInventorySlot() == (Object)null)
{
finishedSlots[0] = true;
}
else if (totemChoices.Count > 0)
{
__instance.CreatePieceInSlot(totemChoices[0], val);
totemChoices.RemoveAt(0);
}
else
{
((InteractableBase)val).SetEnabled(false);
if (((SelectItemsSequencer)__instance).slots.FindAll((SelectableItemSlot a) => ((InteractableBase)a).Enabled).Count == 0)
{
finishedSlots[0] = true;
}
}
}
}
private static IEnumerator WaitForSelectButton(ConfirmStoneButton selectButton, List<bool> finished)
{
yield return selectButton.WaitUntilConfirmation();
finished[1] = true;
}
private static void InitializeSlot(BuildTotemSequencer __instance, ItemData data, SelectableItemSlot selectableItemSlot, Action<MainInputInteractable> callback)
{
Delegate cursorSelectStarted = ((MainInputInteractable)selectableItemSlot).CursorSelectStarted;
((MainInputInteractable)selectableItemSlot).CursorSelectStarted = (Action<MainInputInteractable>)Delegate.Combine(cursorSelectStarted, callback);
((MainInputInteractable)selectableItemSlot).CursorEntered = (Action<MainInputInteractable>)Delegate.Combine(((MainInputInteractable)selectableItemSlot).CursorEntered, (Action<MainInputInteractable>)delegate(MainInputInteractable i)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
Singleton<OpponentAnimationController>.Instance.SetLookTarget(((Component)i).transform, Vector3.up * 2f);
});
}
}
[HarmonyPatch(typeof(SelectItemsSequencer), "DisableSlotsAndExitItems", new Type[] { typeof(SelectableItemSlot) })]
public class SelectItemsSequencer_DisableSlotsAndExitItems
{
public static bool Prefix(SelectItemsSequencer __instance, SelectableItemSlot selectedSlot)
{
if (!Configs.TotemOverrideEnabled)
{
return true;
}
if ((Object)(object)selectedSlot != (Object)null)
{
((ItemSlot)selectedSlot).Item.ShowHighlighted(false, false);
}
__instance.SetSlotCollidersEnabled(false);
foreach (SelectableItemSlot slot in __instance.slots)
{
if ((Object)(object)slot != (Object)(object)selectedSlot && (Object)(object)((ItemSlot)slot).Item != (Object)null && ((InteractableBase)slot).Enabled)
{
((ItemSlot)slot).Item.PlayExitAnimation();
}
}
return false;
}
}
[HarmonyPatch(typeof(BuildTotemSequencer), "GenerateTotemChoices", new Type[]
{
typeof(BuildTotemNodeData),
typeof(int)
})]
public class BuildTotemSequencer_GenerateTotemChoices
{
public static bool Prefix(BuildTotemSequencer __instance, BuildTotemNodeData nodeData, int randomSeed, ref List<ItemData> __result)
{
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Expected O, but got Unknown
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Expected O, but got Unknown
//IL_00df: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
//IL_015c: Unknown result type (might be due to invalid IL or missing references)
//IL_0160: Invalid comparison between Unknown and I4
//IL_0262: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
//IL_02e3: Expected O, but got Unknown
//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
//IL_02f7: Expected O, but got Unknown
//IL_0313: Unknown result type (might be due to invalid IL or missing references)
//IL_0318: Unknown result type (might be due to invalid IL or missing references)
//IL_0325: Unknown result type (might be due to invalid IL or missing references)
//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
if (!Configs.TotemOverrideEnabled)
{
return true;
}
List<Tribe> list = new List<Tribe>
{
(Tribe)2,
(Tribe)3,
(Tribe)4,
(Tribe)6,
(Tribe)5
};
if (StoryEventsData.EventCompleted((StoryEvent)14))
{
list.Add((Tribe)1);
}
foreach (Tribe totemTop in RunState.Run.totemTops)
{
list.Remove(totemTop);
}
int count = list.Count;
List<ItemData> list2 = new List<ItemData>();
for (int i = 0; i < count; i++)
{
TotemTopData val = new TotemTopData();
val.prerequisites = new TriggerCardPrerequisites();
val.prerequisites.tribe = list[SeededRandom.Range(0, list.Count, randomSeed++)];
list.Remove(val.prerequisites.tribe);
list2.Add((ItemData)(object)val);
}
List<Ability> list3 = new List<Ability>();
if (Configs.TotemIncludeUnlearnedAbilities)
{
foreach (object value in Enum.GetValues(typeof(Ability)))
{
Ability val2 = (Ability)value;
if ((int)val2 != 0 && (int)val2 != 107)
{
list3.Add(val2);
}
}
foreach (FullAbility newAbility in AbilityManager.NewAbilities)
{
if (!list3.Contains(newAbility.Id))
{
list3.Add(newAbility.Id);
}
}
}
else
{
list3.AddRange(ProgressionData.Data.learnedAbilities);
}
list3.RemoveAll(delegate(Ability x)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
if (RunState.Run.totemBottoms.Contains(x))
{
return true;
}
AbilityInfo info = AbilitiesUtil.GetInfo(x);
if ((Object)(object)info == (Object)null)
{
return true;
}
if (!Configs.TotemIncludeOverpoweredAbilities && (info.powerLevel > 7 || info.powerLevel < 0))
{
return true;
}
return (!Configs.TotemIncludeNonAct1Abilities && !info.metaCategories.Contains((AbilityMetaCategory)1)) ? true : false;
});
int count2 = list3.Count;
List<ItemData> list4 = new List<ItemData>();
while (list4.Count < count2)
{
int num = int.MaxValue;
int num2 = int.MinValue;
for (int num3 = 0; num3 < list3.Count; num3++)
{
int powerLevel = AbilitiesUtil.GetInfo(list3[num3]).powerLevel;
num = Mathf.Min(num, powerLevel);
num2 = Mathf.Max(num2, powerLevel);
}
int powerLevelRoll = SeededRandom.Range(num, num2, randomSeed++);
List<Ability> list5 = list3.FindAll((Ability x) => AbilitiesUtil.GetInfo(x).powerLevel <= powerLevelRoll);
if (list5.Count > 0)
{
TotemBottomData val3 = new TotemBottomData();
val3.effect = (TotemEffect)0;
val3.effectParams = new EffectParameters();
val3.effectParams.ability = list5[SeededRandom.Range(0, list5.Count, randomSeed++)];
list3.Remove(val3.effectParams.ability);
list4.Add((ItemData)(object)val3);
}
}
__result = TotemsUtil.AlternateTopsAndBottoms(list2, list4);
return false;
}
}
[HarmonyPatch(typeof(CardMergeSequencer), "MergeSequence", new Type[] { typeof(CardMergeNodeData) })]
public class CardMergeSequencer_MergeSequence
{
[HarmonyPrefix]
public static bool Prefix(CardMergeSequencer __instance, CardMergeNodeData nodeData, ref IEnumerator __result)
{
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
if (!Configs.CardMergeOverrideEnabled)
{
return true;
}
Transform val = ((Component)__instance).transform.Find("CustomCancelButton");
if ((Object)(object)val == (Object)null)
{
val = ((Component)__instance).transform.Find("ConfirmStoneButton");
GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, val.parent);
((Object)val2).name = "CustomCancelButton";
((Component)val2.transform.GetChild(0)).gameObject.SetActive(true);
val2.transform.localPosition = new Vector3(3f, 5f, -1.3f);
Transform child = val2.transform.GetChild(0).GetChild(0).GetChild(0)
.GetChild(0);
MeshRenderer component = ((Component)child).GetComponent<MeshRenderer>();
Material[] materials = ((Renderer)component).materials;
materials[0].mainTexture = (Texture)(object)Utils.GetTextureFromPath("Artwork/close_button.png");
((Renderer)component).materials = materials;
val = val2.transform;
}
ConfirmStoneButton componentInChildren = ((Component)val).GetComponentInChildren<ConfirmStoneButton>(true);
__result = Sequence(nodeData, __instance, componentInChildren);
return false;
}
private static IEnumerator Sequence(CardMergeNodeData nodeData, CardMergeSequencer __instance, ConfirmStoneButton cancelButton)
{
yield return Intro(__instance, cancelButton);
Plugin.Log.LogInfo((object)("[Sequence] spawning cards " + __instance.pile.cards.Count + " " + __instance.pile.DoingCardOperation));
yield return __instance.pile.SpawnCards(RunState.DeckList.Count, 0.5f);
Plugin.Log.LogInfo((object)("[Sequence] cards spawned " + __instance.pile.cards.Count + " " + __instance.pile.DoingCardOperation));
List<CardInfo> validHosts = __instance.GetValidCardsForHost((CardInfo)null);
List<CardInfo> validCardsForSacrifice = __instance.GetValidCardsForSacrifice((CardInfo)null);
bool flag = validHosts.Count == 1 && validCardsForSacrifice.Count == 1 && (Object)(object)validHosts[0] == (Object)(object)validCardsForSacrifice[0];
bool flag2 = validCardsForSacrifice.Exists((CardInfo s) => validHosts.Exists((CardInfo h) => __instance.SacrificeOffersNewAbility(h, s)));
if (validHosts.Count == 0 || validCardsForSacrifice.Count == 0 || flag || !flag2)
{
yield return __instance.InvalidCardsSequence();
}
else
{
Coroutine coroutine = ((MonoBehaviour)__instance).StartCoroutine(SacrificeCard(__instance, cancelButton));
yield return cancelButton.WaitUntilConfirmation();
((MonoBehaviour)__instance).StopCoroutine(coroutine);
}
yield return Outro(nodeData, __instance, cancelButton);
}
private static IEnumerator Outro(CardMergeNodeData nodeData, CardMergeSequencer __instance, ConfirmStoneButton cancelButton)
{
Singleton<ViewManager>.Instance.SwitchToView((View)1, false, false);
yield return (object)new WaitForSeconds(0.25f);
__instance.hostSlot.FlyOffCard();
__instance.sacrificeSlot.FlyOffCard();
Plugin.Log.LogInfo((object)("[Outro] destroying cards" + __instance.pile.cards.Count + " " + __instance.pile.DoingCardOperation));
yield return __instance.pile.DestroyCards(0f);
Plugin.Log.LogInfo((object)("[Outro] cards destroyed " + __instance.pile.cards.Count + " " + __instance.pile.DoingCardOperation));
__instance.stoneCircleAnim.SetTrigger("exit");
Transform cancelButtonAnim = ((Component)cancelButton).transform.parent.parent;
((Component)cancelButtonAnim).GetComponent<Animator>().SetTrigger("exit");
EmissionModule emission = __instance.dustParticles.emission;
((EmissionModule)(ref emission)).rateOverTime = new MinMaxCurve(0f, 0f);
yield return (object)new WaitForSeconds(0.25f);
__instance.confirmStone.Exit();
cancelButton.Exit();
yield return (object)new WaitForSeconds(0.75f);
((Component)__instance.stoneCircleAnim).gameObject.SetActive(false);
((Component)cancelButtonAnim).gameObject.SetActive(false);
__instance.confirmStone.SetStoneInactive();
cancelButton.SetStoneInactive();
__instance.sacrificeSlot.DestroyCard();
__instance.hostSlot.DestroyCard();
Singleton<GameFlowManager>.Instance.TransitionToGameState((GameState)1, (NodeData)null);
}
private static IEnumerator Intro(CardMergeSequencer __instance, ConfirmStoneButton buttonParent)
{
Plugin.Log.LogInfo((object)"[Intro] starting");
__instance.hostSlot.Disable();
__instance.sacrificeSlot.Disable();
Singleton<TableRuleBook>.Instance.SetOnBoard(true);
EmissionModule dustEmission = __instance.dustParticles.emission;
((EmissionModule)(ref dustEmission)).rateOverTime = new MinMaxCurve(10f, 10f);
Singleton<ViewManager>.Instance.Controller.SwitchToControlMode((ControlMode)5, false);
Singleton<ViewManager>.Instance.Controller.LockState = (ViewLockState)1;
yield return (object)new WaitForSeconds(0.3f);
((Component)__instance.stoneCircleAnim).gameObject.SetActive(true);
((Component)((Component)buttonParent).transform.parent.parent).gameObject.SetActive(true);
buttonParent.Enter();
yield return (object)new WaitForSeconds(0.5f);
if (!ProgressionData.LearnedMechanic((MechanicsConcept)24))
{
yield return Singleton<TextDisplayer>.Instance.ShowUntilInput("You stumbled into some strange stones in the mist.", -2.5f, 0.5f, (Emotion)0, (LetterAnimation)1, (Speaker)0, (string[])null, true);
}
Plugin.Log.LogInfo((object)"[Intro] done");
}
private static IEnumerator SacrificeCard(CardMergeSequencer __instance, ConfirmStoneButton cancelButton)
{
Plugin.Log.LogInfo((object)"[SacrificeCard] starting");
((InteractableBase)__instance.sacrificeSlot).ClearDelegates();
SelectCardFromDeckSlot selectCardFromDeckSlot = __instance.sacrificeSlot;
((MainInputInteractable)selectCardFromDeckSlot).CursorSelectStarted = (Action<MainInputInteractable>)Delegate.Combine(((MainInputInteractable)selectCardFromDeckSlot).CursorSelectStarted, new Action<MainInputInteractable>(__instance.OnSlotSelected));
((InteractableBase)__instance.hostSlot).ClearDelegates();
SelectCardFromDeckSlot selectCardFromDeckSlot2 = __instance.hostSlot;
((MainInputInteractable)selectCardFromDeckSlot2).CursorSelectStarted = (Action<MainInputInteractable>)Delegate.Combine(((MainInputInteractable)selectCardFromDeckSlot2).CursorSelectStarted, new Action<MainInputInteractable>(__instance.OnSlotSelected));
while (true)
{
Plugin.Log.LogInfo((object)"[SacrificeCard] A");
Singleton<ViewManager>.Instance.SwitchToView((View)8, false, false);
((Behaviour)__instance.gamepadGrid).enabled = true;
__instance.sacrificeSlot.RevealAndEnable();
if (!ProgressionData.LearnedMechanic((MechanicsConcept)24))
{
yield return (object)new WaitForSeconds(0.5f);
Singleton<TextDisplayer>.Instance.Clear();
yield return (object)new WaitForSeconds(0.1f);
Singleton<TextDisplayer>.Instance.ShowMessage("You were compelled to choose a worthy [c:bR]sacrifice.[c:] One that will be lost forever...", (Emotion)0, (LetterAnimation)1, (Speaker)0, (string[])null);
yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)__instance.sacrificeSlot.Card != (Object)null));
yield return (object)new WaitForSeconds(0.25f);
Singleton<TextDisplayer>.Instance.Clear();
}
__instance.hostSlot.RevealAndEnable();
if (!ProgressionData.LearnedMechanic((MechanicsConcept)24))
{
yield return (object)new WaitUntil((Func<bool>)(() => (int)Singleton<ViewManager>.Instance.CurrentView == 2));
Singleton<TextDisplayer>.Instance.Clear();
Singleton<TextDisplayer>.Instance.ShowMessage("You looked upon your menagerie and selected a healthy [c:bR]host.[c:]", (Emotion)0, (LetterAnimation)1, (Speaker)0, (string[])null);
yield return (object)new WaitUntil((Func<bool>)(() => Object.op_Implicit((Object)(object)__instance.hostSlot.Card) || (Object)(object)__instance.sacrificeSlot.Card == (Object)null));
Singleton<TextDisplayer>.Instance.Clear();
}
yield return __instance.confirmStone.WaitUntilConfirmation();
((Behaviour)__instance.gamepadGrid).enabled = false;
__instance.hostSlot.Disable();
__instance.sacrificeSlot.Disable();
cancelButton.Disable();
yield return (object)new WaitForSeconds(0.25f);
Singleton<ViewManager>.Instance.SwitchToView((View)8, false, true);
Singleton<RuleBookController>.Instance.SetShown(false, true);
yield return (object)new WaitForSeconds(1f);
SpecialCardBehaviour[] components = ((Component)__instance.hostSlot.Card).GetComponents<SpecialCardBehaviour>();
foreach (SpecialCardBehaviour specialCardBehaviour in components)
{
yield return specialCardBehaviour.OnSelectedForCardMergeHost();
}
CardInfo sacrificedInfo = ((Card)__instance.sacrificeSlot.Card).Info;
__instance.ModifyHostCard(((Card)__instance.hostSlot.Card).Info, sacrificedInfo);
((CardCollectionInfo)RunState.Run.playerDeck).RemoveCard(sacrificedInfo);
((Card)__instance.sacrificeSlot.Card).Anim.SetSacrificeHoverMarkerShown(false);
((Card)__instance.sacrificeSlot.Card).Anim.PlayDeathAnimation(false);
AudioController.Instance.PlaySound3D("sacrifice_default", (MixerGroup)4, ((Component)__instance).transform.position, 1f, 0f, (Pitch)null, (Repetition)null, (Randomization)null, (Distortion)null, false);
yield return (object)new WaitForSeconds(0.5f);
AudioController.Instance.PlaySound3D("card_blessing", (MixerGroup)4, ((Component)__instance.hostSlot).transform.position, 1f, 0f, new Pitch(0.6f), (Repetition)null, (Randomization)null, (Distortion)null, false);
((Card)__instance.hostSlot.Card).Anim.PlayTransformAnimation();
yield return (object)new WaitForSeconds(0.15f);
((Card)__instance.hostSlot.Card).SetInfo(((Card)__instance.hostSlot.Card).Info);
((Card)__instance.hostSlot.Card).SetInteractionEnabled(false);
((Component)__instance.transformParticles).gameObject.SetActive(false);
((Component)__instance.transformParticles).gameObject.SetActive(true);
yield return (object)new WaitForSeconds(0.25f);
if (!ProgressionData.LearnedMechanic((MechanicsConcept)24))
{
yield return Singleton<TextDisplayer>.Instance.ShowUntilInput(string.Format(Localization.Translate("A ghastly spectactle. But the soul of the [c:bR]{0}[c:] now lives in the [c:bR]{1}[c:]."), sacrificedInfo.DisplayedNameLocalized, ((Card)__instance.hostSlot.Card).Info.DisplayedNameLocalized), -0.65f, 0.4f, (Emotion)0, (LetterAnimation)0, (Speaker)0, (string[])null, true);
ProgressionData.SetMechanicLearned((MechanicsConcept)24);
}
cancelButton.SetButtonInteractable();
if (!AllowMultipleSacrificesOnOneCard())
{
Plugin.Log.LogInfo((object)"Not allowing multiple sacrifices. Waiting for player to remove card");
yield return (object)new WaitForSeconds(0.25f);
__instance.hostSlot.RevealAndEnable();
yield return (object)new WaitWhile((Func<bool>)(() => (Object)(object)__instance.hostSlot.Card != (Object)null));
}
}
}
private static bool AllowMultipleSacrificesOnOneCard()
{
if (Configs.CardMergeAllowMultipleSigilTransfers)
{
return true;
}
if (Plugin.Instance.FuckSacrificeRestrictionsInstalled)
{
return true;
}
return false;
}
}
[HarmonyPatch(typeof(CardMergeSequencer), "OnSlotSelected", new Type[] { typeof(MainInputInteractable) })]
public class CardMergeSequencer_OnSlotSelected
{
public static bool Prefix(CardMergeSequencer __instance, MainInputInteractable slot)
{
if (!Configs.CardMergeOverrideEnabled)
{
return true;
}
Plugin.Log.LogInfo((object)("[OnSlotSelected] " + __instance.pile.cards.Count + " " + __instance.pile.DoingCardOperation));
Transform val = ((Component)__instance).transform.Find("CustomCancelButton");
ConfirmStoneButton componentInChildren = ((Component)val).GetComponentInChildren<ConfirmStoneButton>(true);
componentInChildren.Exit();
return true;
}
}
[HarmonyPatch(typeof(CardMergeSequencer), "OnSelectionEnded", new Type[] { typeof(SelectCardFromDeckSlot) })]
public class CardMergeSequencer_OnSelectionEnded
{
public static bool Prefix(CardMergeSequencer __instance, SelectCardFromDeckSlot slot)
{
if (!Configs.CardMergeOverrideEnabled)
{
return true;
}
Plugin.Log.LogInfo((object)("[OnSelectionEnded] " + __instance.pile.cards.Count + " " + __instance.pile.DoingCardOperation));
Transform val = ((Component)__instance).transform.Find("CustomCancelButton");
ConfirmStoneButton componentInChildren = ((Component)val).GetComponentInChildren<ConfirmStoneButton>(true);
componentInChildren.Enter();
return true;
}
}
[HarmonyPatch(typeof(CardMergeSequencer), "GetValidCardsForSacrifice")]
public class CardMergeSequencer_GetValidCardsForSacrifice
{
[HarmonyPrefix]
public static bool Prefix(ref List<CardInfo> __result, CardMergeSequencer __instance, CardInfo host = null)
{
if (!Configs.CardMergeOverrideEnabled)
{
return true;
}
if (Plugin.Instance.FuckSacrificeRestrictionsInstalled)
{
return false;
}
if (!Configs.CardMergeAllowMultipleSigilTransfers)
{
return true;
}
List<CardInfo> list = new List<CardInfo>(RunState.DeckList);
list.RemoveAll((CardInfo x) => x.NumAbilities == 0);
if ((Object)(object)host != (Object)null)
{
list.RemoveAll((CardInfo s) => !__instance.SacrificeOffersNewAbility(host, s));
}
__result = list;
return false;
}
}
[HarmonyPatch(typeof(CardMergeSequencer), "GetValidCardsForHost")]
public class CardMergeSequencer_CardMergeSequencer
{
[HarmonyPrefix]
public static bool Prefix(ref List<CardInfo> __result, CardMergeSequencer __instance, CardInfo sacrifice = null)
{
if (!Configs.CardMergeOverrideEnabled)
{
return true;
}
if (Plugin.Instance.FuckSacrificeRestrictionsInstalled)
{
return false;
}
if (!Configs.CardMergeAllowMultipleSigilTransfers)
{
return true;
}
List<CardInfo> list = new List<CardInfo>(RunState.DeckList);
if ((Object)(object)sacrifice != (Object)null)
{
list.RemoveAll((CardInfo h) => !__instance.SacrificeOffersNewAbility(h, sacrifice));
}
__result = list;
return false;
}
}
[HarmonyPatch(typeof(CardRemoveSequencer), "OnSlotSelected", new Type[] { typeof(MainInputInteractable) })]
public class CardRemoveSequencer_OnSlotSelected
{
public static bool Prefix(CardRemoveSequencer __instance, MainInputInteractable slot)
{
if (!Configs.CardRemoveOverrideEnabled)
{
return true;
}
Transform val = ((Component)__instance).transform.Find("CustomCancelButton");
ConfirmStoneButton componentInChildren = ((Component)val).GetComponentInChildren<ConfirmStoneButton>(true);
componentInChildren.Exit();
return true;
}
}
[HarmonyPatch(typeof(CardRemoveSequencer), "OnSelectionEnded", new Type[] { })]
public class CardRemoveSequencer_OnSelectionEnded
{
public static bool Prefix(CardRemoveSequencer __instance)
{
if (!Configs.CardRemoveOverrideEnabled)
{
return true;
}
Transform val = ((Component)__instance).transform.Find("CustomCancelButton");
ConfirmStoneButton componentInChildren = ((Component)val).GetComponentInChildren<ConfirmStoneButton>(true);
componentInChildren.Enter();
return true;
}
}
[HarmonyPatch(typeof(CardRemoveSequencer), "RemoveSequence", new Type[] { })]
public class CardRemoveSequencer_RemoveSequence
{
public static bool Prefix(CardRemoveSequencer __instance, ref IEnumerator __result)
{
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
if (!Configs.CardRemoveOverrideEnabled)
{
return true;
}
Transform val = ((Component)__instance).transform.Find("CustomCancelButton");
if ((Object)(object)val == (Object)null)
{
val = ((Component)__instance).transform.Find("ConfirmStoneButton");
GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, val.parent);
((Object)val2).name = "CustomCancelButton";
((Component)val2.transform.GetChild(0)).gameObject.SetActive(true);
val2.transform.localPosition = new Vector3(3f, 5f, -1.3f);
Transform child = val2.transform.GetChild(0).GetChild(0).GetChild(0)
.GetChild(0);
MeshRenderer component = ((Component)child).GetComponent<MeshRenderer>();
Material[] materials = ((Renderer)component).materials;
materials[0].mainTexture = (Texture)(object)Utils.GetTextureFromPath("Artwork/close_button.png");
((Renderer)component).materials = materials;
val = val2.transform;
}
ConfirmStoneButton componentInChildren = ((Component)val).GetComponentInChildren<ConfirmStoneButton>(true);
__result = Sequence(__instance, componentInChildren);
return false;
}
private static IEnumerator Sequence(CardRemoveSequencer __instance, ConfirmStoneButton cancelButton)
{
yield return Intro(__instance, cancelButton);
Coroutine coroutine = ((MonoBehaviour)__instance).StartCoroutine(SacrificeCard(__instance, cancelButton));
yield return cancelButton.WaitUntilConfirmation();
((MonoBehaviour)__instance).StopCoroutine(coroutine);
yield return Outro(__instance, cancelButton);
}
private static IEnumerator Outro(CardRemoveSequencer __instance, ConfirmStoneButton cancelButton)
{
ProgressionData.SetMechanicLearned((MechanicsConcept)25);
yield return ((CardChoicesSequencer)__instance).deckPile.DestroyCards(0f);
__instance.stoneCircleAnim.SetTrigger("exit");
cancelButton.Exit();
Singleton<ExplorableAreaManager>.Instance.ResetHangingLightsToZoneColors(0.25f);
EmissionModule emission = __instance.dustParticles.emission;
((EmissionModule)(ref emission)).rateOverTime = new MinMaxCurve(0f, 0f);
yield return (object)new WaitForSeconds(0.25f);
__instance.confirmStone.Exit();
yield return (object)new WaitForSeconds(0.75f);
((Component)__instance.stoneCircleAnim).gameObject.SetActive(false);
__instance.skullEyes.SetActive(false);
__instance.confirmStone.SetStoneInactive();
RunState.Run.bonelordPuzzleActive = false;
Singleton<GameFlowManager>.Instance.TransitionToGameState((GameState)1, (NodeData)null);
}
private static IEnumerator Intro(CardRemoveSequencer __instance, ConfirmStoneButton cancelButton)
{
__instance.sacrificeSlot.Disable();
Singleton<TableRuleBook>.Instance.SetOnBoard(true);
EmissionModule dustEmission = __instance.dustParticles.emission;
((EmissionModule)(ref dustEmission)).rateOverTime = new MinMaxCurve(10f, 10f);
Singleton<ViewManager>.Instance.Controller.SwitchToControlMode((ControlMode)5, false);
Singleton<ViewManager>.Instance.Controller.LockState = (ViewLockState)1;
yield return (object)new WaitForSeconds(0.3f);
((Component)__instance.stoneCircleAnim).gameObject.SetActive(true);
((Component)((Component)cancelButton).transform.parent.parent).gameObject.SetActive(true);
cancelButton.Enter();
yield return (object)new WaitForSeconds(0.5f);
if (!ProgressionData.LearnedMechanic((MechanicsConcept)25))
{
yield return Singleton<TextDisplayer>.Instance.ShowUntilInput("You came across some familiar stones. But there was something different...", -2.5f, 0.5f, (Emotion)0, (LetterAnimation)1, (Speaker)0, (string[])null, true);
}
yield return ((CardChoicesSequencer)__instance).deckPile.SpawnCards(RunState.DeckList.Count, 0.5f);
Singleton<ViewManager>.Instance.SwitchToView((View)8, false, false);
Singleton<ExplorableAreaManager>.Instance.TweenHangingLightColors(GameColors.Instance.glowRed, GameColors.Instance.orange, 0.1f);
if (!ProgressionData.LearnedMechanic((MechanicsConcept)25))
{
yield return (object)new WaitForSeconds(0.1f);
yield return Singleton<TextDisplayer>.Instance.ShowUntilInput("You intuited that the fate of the creature selected for __instance... would not be pleasant.", -0.65f, 0.4f, (Emotion)0, (LetterAnimation)1, (Speaker)0, (string[])null, true);
}
}
private static IEnumerator SacrificeCard(CardRemoveSequencer __instance, ConfirmStoneButton cancelButton)
{
while (true)
{
cancelButton.SetButtonInteractable();
__instance.sacrificeSlot.RevealAndEnable();
((InteractableBase)__instance.sacrificeSlot).ClearDelegates();
SelectCardFromDeckSlot selectCardFromDeckSlot = __instance.sacrificeSlot;
((MainInputInteractable)selectCardFromDeckSlot).CursorSelectStarted = (Action<MainInputInteractable>)Delegate.Combine(((MainInputInteractable)selectCardFromDeckSlot).CursorSelectStarted, new Action<MainInputInteractable>(__instance.OnSlotSelected));
__instance.sacrificeSlot.backOutInputPressed = null;
SelectCardFromDeckSlot selectCardFromDeckSlot2 = __instance.sacrificeSlot;
selectCardFromDeckSlot2.backOutInputPressed = (Action)Delegate.Combine(selectCardFromDeckSlot2.backOutInputPressed, (Action)delegate
{
if (((InteractableBase)__instance.sacrificeSlot).Enabled)
{
__instance.OnSlotSelected((MainInputInteractable)(object)__instance.sacrificeSlot);
}
});
((Behaviour)((CardChoicesSequencer)__instance).gamepadGrid).enabled = true;
yield return __instance.confirmStone.WaitUntilConfirmation();
cancelButton.Disable();
__instance.sacrificeSlot.Disable();
Singleton<RuleBookController>.Instance.SetShown(false, true);
yield return (object)new WaitForSeconds(0.25f);
SpecialCardBehaviour[] components = ((Component)__instance.sacrificeSlot.Card).GetComponents<SpecialCardBehaviour>();
foreach (SpecialCardBehaviour specialCardBehaviour in components)
{
yield return specialCardBehaviour.OnSelectedForCardRemoval();
}
CardInfo sacrificedInfo = ((Card)__instance.sacrificeSlot.Card).Info;
((CardCollectionInfo)RunState.Run.playerDeck).RemoveCard(sacrificedInfo);
((Card)__instance.sacrificeSlot.Card).Anim.PlayDeathAnimation(false);
AudioController.Instance.PlaySound3D("sacrifice_default", (MixerGroup)4, ((Component)__instance.sacrificeSlot).transform.position, 1f, 0f, (Pitch)null, (Repetition)null, (Randomization)null, (Distortion)null, false);
yield return (object)new WaitForSeconds(0.5f);
__instance.sacrificeSlot.DestroyCard();
if (!sacrificedInfo.HasTrait((Trait)13))
{
if (!ProgressionData.LearnedMechanic((MechanicsConcept)25))
{
yield return Singleton<TextDisplayer>.Instance.ShowUntilInput(string.Format(Localization.Translate("You callously slaughtered the [c:bR]{0}[c:]..."), sacrificedInfo.DisplayedNameLocalized), -0.65f, 0.4f, (Emotion)0, (LetterAnimation)1, (Speaker)0, (string[])null, true);
}
}
else
{
yield return Singleton<TextDisplayer>.Instance.PlayDialogueEvent("CardRemovePeltChosen1", (MessageAdvanceMode)1, (EventIntersectMode)0, (string[])null, (Action<Line>)null);
}
yield return (object)new WaitForSeconds(0.5f);
__instance.skullEyes.SetActive(true);
AudioController.Instance.PlaySound2D("creepy_rattle_lofi", (MixerGroup)0, 1f, 0f, (Pitch)null, (Repetition)null, (Randomization)null, (Distortion)null, false);
yield return (object)new WaitForSeconds(0.5f);
if (sacrificedInfo.HasTrait((Trait)13))
{
yield return Singleton<TextDisplayer>.Instance.PlayDialogueEvent("CardRemovePeltChosen2", (MessageAdvanceMode)1, (EventIntersectMode)0, (string[])null, (Action<Line>)null);
}
else if (sacrificedInfo.HasTrait((Trait)20))
{
yield return Singleton<TextDisplayer>.Instance.PlayDialogueEvent("CardRemoveGoatChosen", (MessageAdvanceMode)1, (EventIntersectMode)0, (string[])null, (Action<Line>)null);
}
else if (!ProgressionData.LearnedMechanic((MechanicsConcept)25))
{
yield return Singleton<TextDisplayer>.Instance.ShowUntilInput("However, the [c:bR]Bone Lord[c:] was pleased by your sacrifice.", 0f, 0.4f, (Emotion)0, (LetterAnimation)1, (Speaker)0, (string[])null, true);
}
if (!sacrificedInfo.HasTrait((Trait)13))
{
SelectableCard boonCard = ((CardChoicesSequencer)__instance).SpawnCard(((Component)__instance).transform);
((Component)boonCard).gameObject.SetActive(true);
if (sacrificedInfo.HasTrait((Trait)20))
{
((Card)boonCard).SetInfo(BoonsUtil.CreateCardForBoon((Type)6));
}
else
{
((Card)boonCard).SetInfo(BoonsUtil.CreateCardForBoon((Type)7));
}
((InteractableBase)boonCard).SetEnabled(false);
((CardChoicesSequencer)__instance).gamepadGrid.Rows[0].interactables.Add((InteractableBase)(object)boonCard);
((Component)boonCard).transform.position = ((Component)__instance.sacrificeSlot).transform.position + Vector3.up * 3f;
((Card)boonCard).Anim.Play("fly_on", 0f);
__instance.sacrificeSlot.PlaceCardOnSlot(((Component)boonCard).transform, 0.5f, 0f, 0f);
yield return (object)new WaitForSeconds(0.5f);
((InteractableBase)boonCard).SetEnabled(true);
SelectableCard selectableCard = boonCard;
((MainInputInteractable)selectableCard).CursorSelectEnded = (Action<MainInputInteractable>)Delegate.Combine(((MainInputInteractable)selectableCard).CursorSelectEnded, new Action<MainInputInteractable>(__instance.OnBoonSelected));
__instance.boonTaken = false;
yield return (object)new WaitUntil((Func<bool>)(() => __instance.boonTaken));
((Behaviour)((CardChoicesSequencer)__instance).gamepadGrid).enabled = false;
((Card)boonCard).Anim.PlayQuickRiffleSound();
Tween.Position(((Component)boonCard).transform, ((Component)boonCard).transform.position + Vector3.back * 4f + Vector3.up * 0.5f, 0.2f, 0f, Tween.EaseInOut, (LoopType)0, (Action)null, (Action)null, true);
Tween.Rotate(((Component)boonCard).transform, new Vector3(0f, 90f, 0f), (Space)0, 0.2f, 0f, (AnimationCurve)null, (LoopType)0, (Action)null, (Action)null, true);
yield return (object)new WaitForSeconds(0.25f);
Object.Destroy((Object)(object)((Component)boonCard).gameObject);
}
}
}
}
[HarmonyPatch(typeof(SpecialNodeHandler), "StartSpecialNodeSequence")]
public class CardStatBoostSequencer_StartSpecialNodeSequence
{
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
MethodInfo original = AccessTools.Method(typeof(CardStatBoostSequencer), "StatBoostSequence", (Type[])null, (Type[])null);
MethodInfo replacement = AccessTools.Method(typeof(CardStatBoostSequencer_StartSpecialNodeSequence), "CreateSequence", (Type[])null, (Type[])null);
int replaced = 0;
foreach (CodeInstruction instruction in instructions)
{
if (CodeInstructionExtensions.Calls(instruction, original))
{
instruction.opcode = OpCodes.Call;
instruction.operand = replacement;
replaced++;
}
yield return instruction;
}
if (replaced != 1)
{
throw new InvalidOperationException("Expected one campfire sequence call in StartSpecialNodeSequence, found " + replaced);
}
}
public static IEnumerator CreateSequence(CardStatBoostSequencer sequencer)
{
IEnumerator __result = null;
if (CardStatBoostSequencer_RemoveSequence.CardStatBoostSequencer_StatBoostSequence(sequencer, ref __result))
{
return sequencer.StatBoostSequence();
}
return __result;
}
}
[HarmonyPatch(typeof(CardStatBoostSequencer), "StatBoostSequence", new Type[] { })]
public class CardStatBoostSequencer_RemoveSequence
{
internal static bool m_IsCancelButtonShowing;
[HarmonyPrefix]
public static bool CardStatBoostSequencer_StatBoostSequence(CardStatBoostSequencer __instance, ref IEnumerator __result)
{
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
if (!Configs.FlameOverrideEnabled)
{
Plugin.Log.LogError((object)"FlameOverrideEnabled is false, returning original enumerator");
return true;
}
Transform transform = ((Component)__instance).transform;
Transform val = transform.Find("CustomCancelButton");
if ((Object)(object)val == (Object)null)
{
val = ((Component)__instance).transform.Find("ConfirmStoneButton");
GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, val.parent);
((Object)val2).name = "CustomCancelButton";
((Component)val2.transform.GetChild(0)).gameObject.SetActive(true);
val2.transform.localPosition = new Vector3(2f, 5f, -0.5f);
Transform child = val2.transform.GetChild(0).GetChild(0).GetChild(0)
.GetChild(0);
MeshRenderer component = ((Component)child).GetComponent<MeshRenderer>();
Material[] materials = ((Renderer)component).materials;
materials[0].mainTexture = (Texture)(object)Utils.GetTextureFromPath("Artwork/close_button.png");
((Renderer)component).materials = materials;
val = val2.transform;
}
else
{
Plugin.Log.LogError((object)"Cancel button found, using existing one");
}
ConfirmStoneButton componentInChildren = ((Component)val).GetComponentInChildren<ConfirmStoneButton>(true);
Debug.Assert(Object.op_Implicit((Object)(object)componentInChildren), "cancelButton is null but the gameObject is not");
componentInChildren.confirmView = (View)1;
((Component)val).gameObject.SetActive(true);
((Component)((Component)componentInChildren).transform.parent.parent).gameObject.SetActive(true);
m_IsCancelButtonShowing = false;
__result = Sequence(__instance, componentInChildren);
return false;
}
private static IEnumerator Sequence(CardStatBoostSequencer __instance, ConfirmStoneButton cancelButton)
{
Plugin.Log.LogInfo((object)"[Campfire] Starting unlimited buffs with exit button.");
bool killSurvivors = false;
bool attackMod;
if (__instance.GetValidCards(true).Count == 0)
{
attackMod = false;
}
else if (!ProgressionData.LearnedMechanic((MechanicsConcept)42))
{
attackMod = true;
}
else
{
attackMod = SeededRandom.Bool(SaveManager.SaveFile.GetCurrentRandomSeed());
}
((HighlightedInteractable)__instance.selectionSlot).specificRenderers[0].material.mainTexture = (attackMod ? __instance.attackModSlotTexture : __instance.healthModSlotTexture);
__instance.figurines.ForEach(delegate(CompositeFigurine x)
{
x.SetArms((FigurineType)((!attackMod) ? 1 : 3));
});
__instance.figurines.ForEach(delegate(CompositeFigurine x)
{
((Component)x).gameObject.SetActive(false);
});
__instance.stakeRingParent.SetActive(false);
((Component)__instance.campfireLight).gameObject.SetActive(false);
__instance.campfireLight.intensity = 0f;
__instance.campfireCardLight.intensity = 0f;
__instance.selectionSlot.Disable();
((Component)__instance.selectionSlot).gameObject.SetActive(false);
yield return (object)new WaitForSeconds(0.3f);
((Component)Singleton<ExplorableAreaManager>.Instance.HangingLight).gameObject.SetActive(false);
((Component)Singleton<ExplorableAreaManager>.Instance.HandLight).gameObject.SetActive(false);
Singleton<ViewManager>.Instance.SwitchToView((View)1, false, true);
Singleton<ViewManager>.Instance.OffsetPosition(new Vector3(0f, 0f, 2.25f), 0.1f);
yield return (object)new WaitForSeconds(1f);
if (!RunState.Run.survivorsDead)
{
__instance.figurines.ForEach(delegate(CompositeFigurine x)
{
((Component)x).gameObject.SetActive(true);
});
}
__instance.stakeRingParent.SetActive(true);
((Component)Singleton<ExplorableAreaManager>.Instance.HandLight).gameObject.SetActive(true);
((Component)__instance.campfireLight).gameObject.SetActive(true);
((Component)__instance.selectionSlot).gameObject.SetActive(true);
__instance.selectionSlot.RevealAndEnable();
((InteractableBase)__instance.selectionSlot).ClearDelegates();
SelectCardFromDeckSlot selectCardFromDeckSlot = __instance.selectionSlot;
((MainInputInteractable)selectCardFromDeckSlot).CursorSelectStarted = (Action<MainInputInteractable>)Delegate.Combine(((MainInputInteractable)selectCardFromDeckSlot).CursorSelectStarted, (Action<MainInputInteractable>)delegate(MainInputInteractable i)
{
__instance.OnSlotSelected(i, attackMod);
});
if (Random.value < 0.25f && (Object)(object)Singleton<VideoCameraRig>.Instance != (Object)null)
{
Singleton<VideoCameraRig>.Instance.PlayCameraAnim("refocus_quick");
}
AudioController.Instance.PlaySound3D("campfire_light", (MixerGroup)4, ((Component)__instance.selectionSlot).transform.position, 1f, 0f, (Pitch)null, (Repetition)null, (Randomization)null, (Distortion)null, false);
AudioController.Instance.SetLoopAndPlay("campfire_loop", 1, true, true);
AudioController.Instance.SetLoopVolumeImmediate(0f, 1);
AudioController.Instance.FadeInLoop(0.5f, 0.75f, new int[1] { 1 });
Singleton<InteractionCursor>.Instance.SetEnabled(false);
yield return (object)new WaitForSeconds(0.25f);
yield return __instance.pile.SpawnCards(RunState.DeckList.Count, 0.5f);
Singleton<TableRuleBook>.Instance.SetOnBoard(true);
Singleton<InteractionCursor>.Instance.SetEnabled(true);
if (RunState.Run.survivorsDead)
{
yield return Singleton<TextDisplayer>.Instance.PlayDialogueEvent("StatBoostSurvivorsDead", (MessageAdvanceMode)1, (EventIntersectMode)0, (string[])null, (Action<Line>)null);
}
else
{
yield return Singleton<TextDisplayer>.Instance.PlayDialogueEvent("StatBoostIntro", (MessageAdvanceMode)1, (EventIntersectMode)0, new string[1] { __instance.GetTranslatedStatText(attackMod) }, (Action<Line>)null);
}
int attempt = 0;
int randomSeed = SaveManager.SaveFile.GetCurrentRandomSeed();
cancelButton.Enter();
while (true)
{
if (__instance.GetValidCards(attackMod).Count > 0)
{
__instance.selectionSlot.RevealAndEnable();
}
else
{
__instance.selectionSlot.Disable();
}
if ((Object)(object)__instance.selectionSlot.Card != (Object)null)
{
((Card)__instance.selectionSlot.Card).SetInteractionEnabled(true);
__instance.confirmStone.Unpress();
}
else
{
__instance.confirmStone.Exit();
__instance.confirmStone.Disable();
}
((Component)((Component)cancelButton).transform.parent.parent).gameObject.SetActive(true);
m_IsCancelButtonShowing = true;
cancelButton.Unpress();
Coroutine confirm = ((MonoBehaviour)__instance).StartCoroutine(__instance.confirmStone.WaitUntilConfirmation());
Coroutine exit = ((MonoBehaviour)__instance).StartCoroutine(cancelButton.WaitUntilConfirmation());
try
{
yield return (object)new WaitUntil((Func<bool>)(() => cancelButton.SelectionConfirmed || (__instance.confirmStone.SelectionConfirmed && (Object)(object)__instance.selectionSlot.Card != (Object)null)));
}
finally
{
((MonoBehaviour)__instance).StopCoroutine(confirm);
((MonoBehaviour)__instance).StopCoroutine(exit);
((InteractableBase)__instance.confirmStone).ClearDelegates();
((InteractableBase)cancelButton).ClearDelegates();
}
bool exitRequested = cancelButton.SelectionConfirmed;
m_IsCancelButtonShowing = false;
cancelButton.Disable();
__instance.confirmStone.Disable();
__instance.selectionSlot.Disable();
Singleton<TextDisplayer>.Instance.Clear();
Singleton<RuleBookController>.Instance.SetShown(false, true);
if (exitRequested)
{
break;
}
CardInfo cardInfo = ((Card)__instance.selectionSlot.Card).Info;
((Card)__instance.selectionSlot.Card).SetInteractionEnabled(false);
float chance = Configs.FlameDestroyCardChance / 100f;
float roll = SeededRandom.Value(randomSeed + attempt++);
if (!RunState.Run.survivorsDead && !killSurvivors && (chance >= 1f || (chance > 0f && roll < chance)))
{
__instance.confirmStone.Exit();
__instance.confirmStone.SelectionConfirmed = false;
if (cardInfo.HasTrait((Trait)19) || cardInfo.HasAbility((Ability)4))
{
killSurvivors = true;
RunState.Run.survivorsDead = true;
}
((Card)__instance.selectionSlot.Card).Anim.PlayDeathAnimation(true);
((CardCollectionInfo)RunState.Run.playerDeck).RemoveCard(cardInfo);
yield return (object)new WaitForSeconds(1f);
yield return Singleton<TextDisplayer>.Instance.PlayDialogueEvent("StatBoostCardEaten", (MessageAdvanceMode)1, (EventIntersectMode)0, new string[1] { cardInfo.DisplayedNameLocalized }, (Action<Line>)null);
__instance.selectionSlot.DestroyCard();
yield return null;
if (killSurvivors)
{
__instance.figurines.ForEach(delegate(CompositeFigurine x)
{
((Component)x).gameObject.SetActive(false);
});
}
if (RunState.Run.consumables.Count < RunState.Run.MaxConsumables)
{
Singleton<ViewManager>.Instance.SwitchToView((View)32, false, false);
yield return (object)new WaitForSeconds(0.2f);
RunState.Run.consumables.Add("PiggyBank");
Singleton<ItemsManager>.Instance.UpdateItems(false);
yield return (object)new WaitForSeconds(0.5f);
yield return Singleton<TextDisplayer>.Instance.PlayDialogueEvent("StatBoostCardEatenBones", (MessageAdvanceMode)1, (EventIntersectMode)0, (string[])null, (Action<Line>)null);
}
Singleton<ViewManager>.Instance.SwitchToView((View)1, false, false);
}
else
{
yield return (object)new WaitForSeconds(0.25f);
AudioController.Instance.PlaySound3D("card_blessing", (MixerGroup)4, ((Component)__instance.selectionSlot).transform.position, 1f, 0f, (Pitch)null, (Repetition)null, (Randomization)null, (Distortion)null, false);
((Card)__instance.selectionSlot.Card).Anim.PlayTransformAnimation();
__instance.ApplyModToCard(cardInfo, attackMod);
yield return (object)new WaitForSeconds(0.15f);
((Card)__instance.selectionSlot.Card).SetInfo(cardInfo);
yield return (object)new WaitForSeconds(0.75f);
}
}
((InteractableBase)__instance.selectionSlot).ClearDelegates();
((Component)__instance.retrieveCardInteractable).gameObject.SetActive(false);
if ((Object)(object)__instance.selectionSlot.Card != (Object)null)
{
yield return Singleton<TextDisplayer>.Instance.PlayDialogueEvent("StatBoostOutro", (MessageAdvanceMode)1, (EventIntersectMode)0, new string[2]
{
__instance.GetTranslatedStatText(attackMod),
((Card)__instance.selectionSlot.Card).Info.DisplayedNameLocalized
}, (Action<Line>)null);
}
SaveManager.SaveToFile(true);
yield return (object)new WaitForSeconds(0.1f);
if ((Object)(object)__instance.selectionSlot.Card != (Object)null)
{
__instance.selectionSlot.FlyOffCard();
}
Singleton<ViewManager>.Instance.SwitchToView((View)1, false, false);
yield return (object)new WaitForSeconds(0.25f);
AudioController.Instance.PlaySound3D("campfire_putout", (MixerGroup)4, ((Component)__instance.selectionSlot).transform.position, 1f, 0f, (Pitch)null, (Repetition)null, (Randomization)null, (Distortion)null, false);
AudioController.Instance.StopLoop(1);
((Component)__instance.campfireLight).gameObject.SetActive(false);
((Component)Singleton<ExplorableAreaManager>.Instance.HandLight).gameObject.SetActive(false);
yield return __instance.pile.DestroyCards(0.5f);
yield return (object)new WaitForSeconds(0.2f);
__instance.figurines.ForEach(delegate(CompositeFigurine x)
{
((Component)x).gameObject.SetActive(false);
});
__instance.stakeRingParent.SetActive(false);
__instance.confirmStone.SetStoneInactive();
((Component)__instance.selectionSlot).gameObject.SetActive(false);
cancelButton.SetStoneInactive();
CustomCoroutine.WaitThenExecute(0.4f, (Action)delegate
{
Singleton<ExplorableAreaManager>.Instance.HangingLight.intensity = 0f;
((Component)Singleton<ExplorableAreaManager>.Instance.HangingLight).gameObject.SetActive(true);
Singleton<ExplorableAreaManager>.Instance.HandLight.intensity = 0f;
((Component)Singleton<ExplorableAreaManager>.Instance.HandLight).gameObject.SetActive(true);
}, false);
if (killSurvivors && !RunState.Run.survivorsDead)
{
RunState.Run.survivorsDead = true;
}
ProgressionData.SetMechanicLearned((MechanicsConcept)42);
if ((Object)(object)Singleton<GameFlowManager>.Instance != (Object)null)
{
Singleton<GameFlowManager>.Instance.TransitionToGameState((GameState)1, (NodeData)null);
}
}
}
[HarmonyPatch(typeof(CardStatBoostSequencer), "OnSlotSelected")]
public class CardStatBoostSequencer_OnSlotSelected
{
public static bool Prefix(CardStatBoostSequencer __instance, MainInputInteractable slot)
{
if (!Configs.FlameOverrideEnabled || !CardStatBoostSequencer_RemoveSequence.m_IsCancelButtonShowing)
{
return true;
}
__instance.confirmStone.SelectionConfirmed = false;
Transform val = ((Component)__instance).transform.Find("CustomCancelButton");
Debug.Assert(Object.op_Implicit((Object)(object)val), "Confirm stone button not created yet!");
ConfirmStoneButton componentInChildren = ((Component)val).GetComponentInChildren<ConfirmStoneButton>(true);
componentInChildren.Exit();
return true;
}
}
[HarmonyPatch(typeof(CardStatBoostSequencer), "OnSelectionEnded")]
public class CardStatBoostSequencer_OnSelectionEnded
{
public static bool Prefix(CardStatBoostSequencer __instance)
{
if (!Configs.FlameOverrideEnabled || !CardStatBoostSequencer_RemoveSequence.m_IsCancelButtonShowing)
{
return true;
}
__instance.confirmStone.SelectionConfirmed = false;
Transform val = ((Component)__instance).transform.Find("CustomCancelButton");
Debug.Assert(Object.op_Implicit((Object)(object)val), "Confirm stone button not created yet!");
ConfirmStoneButton componentInChildren = ((Component)val).GetComponentInChildren<ConfirmStoneButton>(true);
componentInChildren.Enter();
return true;
}
}
[HarmonyPatch(typeof(SpecialNodeHandler), "StartSpecialNodeSequence")]
public class CopyCardSequencer_StartSpecialNodeSequence
{
[ThreadStatic]
internal static bool AdvancingPainting;
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
MethodInfo original = AccessTools.Method(typeof(CopyCardSequencer), "CopyCardSequence", (Type[])null, (Type[])null);
MethodInfo replacement = AccessTools.Method(typeof(CopyCardSequencer_StartSpecialNodeSequence), "CreateSequence", (Type[])null, (Type[])null);
int replaced = 0;
foreach (CodeInstruction instruction in instructions)
{
if (CodeInstructionExtensions.Calls(instruction, original))
{
instruction.opcode = OpCodes.Call;
instruction.operand = replacement;
replaced++;
}
yield return instruction;
}
if (replaced != 1)
{
throw new InvalidOperationException("Expected one Goobert sequence call in StartSpecialNodeSequence, found " + replaced);
}
}
public static IEnumerator CreateSequence(CopyCardSequencer sequencer)
{
return Configs.CopyCardOverrideEnabled ? RepeatSequence(sequencer) : sequencer.CopyCardSequence();
}
private static IEnumerator RepeatSequence(CopyCardSequencer sequencer)
{
Transform template = ((Component)sequencer).transform.Find("ConfirmStoneButton");
if ((Object)(object)template == (Object)null)
{
throw new InvalidOperationException("Goobert's ConfirmStoneButton template was not found.");
}
GameObject repeatObject = null;
GameObject exitObject = null;
try
{
repeatObject = Object.Instantiate<GameObject>(((Component)template).gameObject, template.parent);
exitObject = Object.Instantiate<GameObject>(((Component)template).gameObject, template.parent);
ConfirmStoneButton repeatButton = PrepareButton(repeatObject, "CustomCopyRepeatButton", -3f);
ConfirmStoneButton exitButton = PrepareButton(exitObject, "CustomCopyExitButton", 3f);
MeshRenderer icon = ((Component)exitObject.transform.GetChild(0).GetChild(0).GetChild(0)
.GetChild(0)).GetComponent<MeshRenderer>();
((Renderer)icon).material.mainTexture = (Texture)(object)Utils.GetTextureFromPath("Artwork/close_button.png");
Plugin.Log.LogInfo((object)"[Goobert] Starting repeatable paintings.");
bool leave;
do
{
IEnumerator painting = sequencer.CopyCardSequence();
try
{
while (AdvancePainting(painting))
{
yield return painting.Current;
}
}
finally
{
IDisposable disposable = painting as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
yield return (object)new WaitUntil((Func<bool>)(() => !sequencer.pile.DoingCardOperation));
((InteractableBase)sequencer.selectionSlot).ClearDelegates();
sequencer.selectionSlot.Disable();
((InteractableBase)sequencer.confirmStone).ClearDelegates();
sequencer.confirmStone.SetStoneInactive();
Singleton<TextDisplayer>.Instance.ShowMessage("Paint another card? Or leave?", (Emotion)0, (LetterAnimation)1, (Speaker)0, (string[])null);
bool canRepeat = RunState.DeckList.Count > 0;
if (canRepeat)
{
repeatButton.Enter();
}
exitButton.Enter();
Coroutine repeatWait = (canRepeat ? ((MonoBehaviour)sequencer).StartCoroutine(repeatButton.WaitUntilConfirmation()) : null);
Coroutine exitWait = ((MonoBehaviour)sequencer).StartCoroutine(exitButton.WaitUntilConfirmation());
try
{
yield return (object)new WaitUntil((Func<bool>)(() => exitButton.SelectionConfirmed || (canRepeat && repeatButton.SelectionConfirmed)));
leave = exitButton.SelectionConfirmed;
}
finally
{
if (repeatWait != null)
{
((MonoBehaviour)sequencer).StopCoroutine(repeatWait);
}
((MonoBehaviour)sequencer).StopCoroutine(exitWait);
((InteractableBase)repeatButton).ClearDelegates();
((InteractableBase)exitButton).ClearDelegates();
repeatButton.SetStoneInactive();
exitButton.SetStoneInactive();
Singleton<TextDisplayer>.Instance.Clear();
}
}
while (!leave);
}
finally
{
if ((Object)(object)repeatObject != (Object)null)
{
Object.Destroy((Object)(object)repeatObject);
}
if ((Object)(object)exitObject != (Object)null)
{
Object.Destroy((Object)(object)exitObject);
}
}
if ((Object)(object)Singleton<GameFlowManager>.Instance != (Object)null)
{
Singleton<GameFlowManager>.Instance.TransitionToGameState((GameState)1, (NodeData)null);
}
}
private static ConfirmStoneButton PrepareButton(GameObject clone, string name, float x)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
((Object)clone).name = name;
clone.transform.localPosition = new Vector3(x, 5f, -1.3f);
clone.SetActive(true);
((Component)clone.transform.GetChild(0)).gameObject.SetActive(true);
ConfirmStoneButton componentInChildren = clone.GetComponentInChildren<ConfirmStoneButton>(true);
componentInChildren.confirmView = (View)1;
((InteractableBase)componentInChildren).ClearDelegates();
componentInChildren.SetStoneInactive();
return componentInChildren;
}
private static bool AdvancePainting(IEnumerator painting)
{
bool advancingPainting = AdvancingPainting;
AdvancingPainting = true;
try
{
return painting.MoveNext();
}
finally
{
AdvancingPainting = advancingPainting;
}
}
}
[HarmonyPatch]
public class CopyCardSequencer_FinishPainting
{
private static MethodBase TargetMethod()
{
return AccessTools.EnumeratorMoveNext((MethodBase)AccessTools.Method(typeof(CopyCardSequencer), "CopyCardSequence", (Type[])null, (Type[])null));
}
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
MethodInfo original = AccessTools.Method(typeof(GameFlowManager), "TransitionToGameState", (Type[])null, (Type[])null);
MethodInfo replacement = AccessTools.Method(typeof(CopyCardSequencer_FinishPainting), "TransitionAfterPainting", (Type[])null, (Type[])null);
int replaced = 0;
foreach (CodeInstruction instruction in instructions)
{
if (CodeInstructionExtensions.Calls(instruction, original))
{
instruction.opcode = OpCodes.Call;
instruction.operand = replacement;
replaced++;
}
yield return instruction;
}
if (replaced != 1)
{
throw new InvalidOperationException("Expected one Goobert map transition, found " + replaced);
}
}
public static void TransitionAfterPainting(GameFlowManager manager, GameState state, NodeData nodeData)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Invalid comparison between Unknown and I4
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
if ((int)state != 1 || !CopyCardSequencer_StartSpecialNodeSequence.AdvancingPainting)
{
manager.TransitionToGameState(state, nodeData);
}
}
}
[HarmonyPatch(typeof(SpecialNodeHandler), "StartSpecialNodeSequence")]
public class DuplicateMergeSequencer_StartSpecialNodeSequence
{
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
MethodInfo original = AccessTools.Method(typeof(DuplicateMergeSequencer), "MergeSequence", (Type[])null, (Type[])null);
MethodInfo replacement = AccessTools.Method(typeof(DuplicateMergeSequencer_StartSpecialNodeSequence), "CreateSequence", (Type[])null, (Type[])null);
int replaced = 0;
foreach (CodeInstruction instruction in instructions)
{
if (CodeInstructionExtensions.Calls(instruction, original))
{
instruction.opcode = OpCodes.Call;
instruction.operand = replacement;
replaced++;
}
yield return instruction;
}
if (replaced != 1)
{
throw new InvalidOperationException("Expected one duplicate-merge sequence call in StartSpecialNodeSequence, found " + replaced);
}
}
public static IEnumerator CreateSequence(DuplicateMergeSequencer sequencer)
{
IEnumerator __result = null;
if (DuplicateMergeSequencer_MergeSequence.Prefix(sequencer, ref __result))
{
return sequencer.MergeSequence();
}
return __result;
}
}
[HarmonyPatch(typeof(DuplicateMergeSequencer), "MergeSequence", new Type[] { })]
public class DuplicateMergeSequencer_MergeSequence
{
public static bool Prefix(DuplicateMergeSequencer __instance, ref IEnumerator __result)
{
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
if (!Configs.DuplicateMergeOverrideEnabled)
{
return true;
}
Transform val = ((Component)__instance).transform.Find("CustomCancelButton");
if ((Object)(object)val == (Object)null)
{
val = ((Component)__instance).transform.Find("ConfirmStoneButton");
GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, val.parent);
((Object)val2).name = "CustomCancelButton";
((Component)val2.transform.GetChild(0)).gameObject.SetActive(true);
val2.transform.localPosition = new Vector3(3f, 5f, -1.3f);
Transform child = val2.transform.GetChild(0).GetChild(0).GetChild(0)
.GetChild(0);
MeshRenderer component = ((Component)child).GetComponent<MeshRenderer>();
Material[] materials = ((Renderer)component).materials;
materials[0].mainTexture = (Texture)(object)Utils.GetTextureFromPath("Artwork/close_button.png");
((Renderer)component).materials = materials;
val = val2.transform;
}
ConfirmStoneButton componentInChildren = ((Component)val).GetComponentInChildren<ConfirmStoneButton>(true);
__result = Sequence(__instance, componentInChildren);
return false;
}
private static IEnumerator Sequence(DuplicateMergeSequencer __instance, ConfirmStoneButton cancelButton)
{
Plugin.Log.LogInfo((object)"[DuplicateMerge] Starting repeatable merges with exit button.");
yield return Intro(__instance);
if (__instance.GetValidDuplicateCards().Count == 0)
{
yield return __instance.SelectDuplicateSequence();
}
else
{
AudioController.Instance.PlaySound3D("mushroom_large_appear", (MixerGroup)4, __instance.largeMushroom.transform.position, 1f, 0f, (Pitch)null, (Repetition)null, (Randomization)null, (Distortion)null, false);
CustomCoroutine.WaitThenExecute(0.8f, (Action)delegate
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
AudioController.Instance.PlaySound3D("mushroom_large_hit", (MixerGroup)4, __instance.largeMushroom.transform.position, 1f, 0f, (Pitch)null, (Repetition)null, (Randomization)null, (Distortion)null, false);
}, false);
__instance.largeMushroom.SetActive(true);
yield return (object)new WaitForSeconds(0.5f);
foreach (GameObject mushroom in __instance.slotMushrooms)
{
mushroom.SetActive(true);
yield return (object)new WaitForSeconds(0.05f);
mushroom.GetComponent<Collider>().enabled = true;
}
List<bool> done = new List<bool> { false, false };
Coroutine doneSacrificing = ((MonoBehaviour)__instance).StartCoroutine(SacrificeCard(__instance, cancelButton, done));
Coroutine waitForCancel = ((MonoBehaviour)__instance).StartCoroutine(WaitUntilConfirmation(cancelButton, done));
yield return (object)new WaitUntil((Func<bool>)(() => done[0] || done[1]));
if (doneSacrificing != null)
{
((MonoBehaviour)__instance).StopCoroutine(doneSacrificing);
}
if (waitForCancel != null)
{
((MonoBehaviour)__instance).StopCoroutine(waitForCancel);
}
}
yield return Outro(__instance, cancelButton);
}
private static IEnumerator WaitUntilConfirmation(ConfirmStoneButton cancelButton, List<bool> done)
{
yield return cancelButton.WaitUntilConfirmation();
done[1] = true;
}
private static IEnumerator Intro(DuplicateMergeSequencer __instance)
{
((Component)__instance.selectionSlot).gameObject.SetActive(true);
((SelectCardFromDeckSlot)__instance.selectionSlot).Disable();
Singleton<TableRuleBook>.Instance.SetOnBoard(true);
Singleton<ViewManager>.Instance.SwitchToView((View)1, false, false);
yield return (object)new WaitForSeconds(0.2f);
AudioController.Instance.PlaySound3D("mushrooms_small_appear", (MixerGroup)4, __instance.largeMushroom.transform.position, 1f, 0f, (Pitch)null, (Repetition)null, (Randomization)null, (Distortion)null, false);
foreach (GameObject mushroom in __instance.mushrooms)
{
mushroom.SetActive(true);
yield return (object)new WaitForSeconds(0.05f);
mushroom.GetComponent<Collider>().enabled = true;
}
if (!ProgressionData.LearnedMechanic((MechanicsConcept)31))
{
yield return Singleton<TextDisplayer>.Instance.PlayDialogueEvent("DuplicateMergeIntro", (MessageAdvanceMode)1, (EventIntersectMode)0, (string[])null, (Action<Line>)null);
}
LeshyAnimationController.Instance.PutOnMask((Mask)5, true);
yield return (object)new WaitForSeconds(1f);
Singleton<ViewManager>.Instance.SwitchToView((View)29, false, true);
Singleton<OpponentAnimationController>.Instance.SetHeadTrigger("doctor_idle");
yield return Singleton<TextDisplayer>.Instance.PlayDialogueEvent("DoctorIntro", (MessageAdvanceMode)1, (EventIntersectMode)0, (string[])null, (Action<Line>)__instance.OnDoctorDialogueLine);
__instance.SetSideHeadTalking(false);
Singleton<ViewManager>.Instance.SwitchToView((View)1, false, false);
yield return (object)new WaitForSeconds(0.1f);
}
private static IEnumerator Outro(DuplicateMergeSequencer __instance, ConfirmStoneButton cancelButton)
{
((MonoBehaviour)__instance).StartCoroutine(LeshyAnimationController.Instance.TakeOffMask());
cancelButton.Exit();
((SelectCardFromDeckSlot)__instance.selectionSlot).FlyOffCard();
yield return __instance.pile.DestroyCards(0.5f);
yield return __instance.CleanUp();
if ((Object)(object)Singleton<GameFlowManager>.Instance != (Object)null)
{
Singleton<GameFlowManager>.Instance.TransitionToGameState((GameState)1, (NodeData)null);
}
}
private static IEnumerator SacrificeCard(DuplicateMergeSequencer __instance, ConfirmStoneButton cancelButton, List<bool> bools)
{
while (__instance.GetValidDuplicateCards().Count > 0)
{
yield return __instance.pile.SpawnCards(RunState.DeckList.Count, 0.5f);
((Component)((Component)cancelButton).transform.parent.parent).gameObject.SetActive(true);
cancelButton.Enter();
((HighlightedInteractable)__instance.selectionSlot).SetShown(true, false);
((HighlightedInteractable)__instance.selectionSlot).ShowState((State)2, false, 0.15f);
Singleton<ViewManager>.Instance.SwitchToView((View)8, false, true);
((Component)__instance.selectionSlot).gameObject.SetActive(true);
((SelectCardFromDeckSlot)__instance.selectionSlot).RevealAndEnable();
((InteractableBase)__instance.selectionSlot).ClearDelegates();
SelectCardPairFromDeckSlot selectCardPairFromDeckSlot = __instance.selectionSlot;
((MainInputInteractable)selectCardPairFromDeckSlot).CursorSelectStarted = (Action<MainInputInteractable>)Delegate.Combine(((MainInputInteractable)selectCardPairFromDeckSlot).CursorSelectStarted, new Action<MainInputInteractable>(__instance.OnSlotSelected));
yield return __instance.confirmStone.WaitUntilConfirmation();
cancelButton.Disable();
((InteractableBase)__instance.selectionSlot).ClearDelegates();
Singleton<RuleBookController>.Instance.SetShown(false, true);
yield return CombinePair(__instance, __instance.selectionSlot.SelectedPair);
ProgressionData.SetMechanicLearned((MechanicsConcept)31);
}
bools[0] = true;
}
private static IEnumerator CombinePair(DuplicateMergeSequencer __instance, SelectableCardPair pair)
{
Singleton<ViewManager>.Instance.SwitchToView((View)1, false, false);
yield return (object)new WaitForSeconds(0.15f);
LeshyAnimationController.Instance.RightArm.PlayAnimation("doctor_hand_intro");
yield return Singleton<TextDisplayer>.Instance.PlayDialogueEvent("DuplicateMergeLookAway", (MessageAdvanceMode)1, (EventIntersectMode)0, (string[])null, (Action<Line>)__instance.OnDoctorDialogueLine);
__instance.SetSideHeadTalking(false);
Singleton<ViewManager>.Instance.SwitchToView((View)31, false, false);
AudioController.Instance.PlaySound3D("mycologist_carnage", (MixerGroup)4, __instance.largeMushroom.transform.position, 1f, 0f, (Pitch)null, (Repetition)null, (Randomization)null, (Distortion)null, false);
yield return (object)new WaitForSeconds(1f);
Singleton<CameraEffects>.Instance.Shake(0.1f, 0.25f);
((Component)__instance.bloodParticles1).gameObject.SetActive(true);
yield return (object)new WaitForSeconds(0.5f);
Singleton<CameraEffects>.Instance.Shake(0.05f, 0.4f);
((Component)__instance.paperParticles).gameObject.SetActive(true);
yield return (object)new WaitForSeconds(1f);
((Component)__instance.bloodParticles2).gameObject.SetActive(true);
Singleton<CameraEffects>.Instance.Shake(0.1f, 0.4f);
yield return (object)new WaitForSeconds(0.5f);
if (((Card)pair.LeftCard).Info.Mods.Exists((CardModificationInfo x) => x.fromDuplicateMerge) || ((Card)pair.RightCard).Info.Mods.Exists((CardModificationInfo x) => x.fromDuplicateMerge))
{
AchievementManager.Unlock((Achievement)15);
}
CardInfo info = __instance.MergeCards(((Card)pair.LeftCard).Info, ((Card)pair.RightCard).Info);
__instance.mergedCard = __instance.SpawnMergedCard(info, ((Component)pair).transform.position, ((Component)pair).transform.eulerAngles);
((SelectCardFromDeckSlot)__instance.selectionSlot).DestroyCard();
((Component)__instance.selectionSlot).gameObject.SetActive(false);
Singleton<ViewManager>.Instance.SwitchToView((View)8, false, false);
yield return (object)new WaitForSeconds(0.15f);
yield return Singleton<TextDisplayer>.Instance.PlayDialogueEvent("DuplicateMergeResult", (MessageAdvanceMode)1, (EventIntersectMode)0, new string[1] { ((Card)pair.LeftCard).Info.DisplayedNameLocalized }, (Action<Line>)null);
Singleton<ViewManager>.Instance.SwitchToView((View)1, false, false);
yield return (object)new WaitForSeconds(0.1f);
((Card)__instance.mergedCard).ExitBoard(0.4f, new Vector3(1f, 0f, -2f));
yield return (object)new WaitForSeconds(0.5f);
LeshyAnimationController.Instance.RightArm.SetTrigger("doctor_hide");
CustomCoroutine.WaitThenExecute(1f, (Action)delegate
{
LeshyAnimationController.Instance.RightArm.SetHidden(true);
}, false);
((Component)__instance.bloodParticles1).gameObject.SetActive(false);
((Component)__instance.bloodParticles2).gameObject.SetActive(false);
((Component)__instance.paperParticles).gameObject.SetActive(false);
}
}
[HarmonyPatch(typeof(DuplicateMergeSequencer), "GetValidDuplicateCards", new Type[] { })]
public class DuplicateMergeSequencer_GetValidDuplicateCards
{
public static bool Prefix(DuplicateMergeSequencer __instance, ref List<CardInfo> __result)
{
if (!Configs.DuplicateMergeOverrideEnabled)
{
return true;
}
List<CardInfo> list = new List<CardInfo>(RunState.DeckList);
list.RemoveAll((CardInfo a) => ((Object)a).name.Contains("DEATHCARD"));
for (int num = 0; num < list.Count; num++)
{
CardInfo card = list[num];
if (list.FindAll((CardInfo x) => ((Object)x).name == ((Object)card).name).Count % 2 != 0)
{
list.RemoveAt(num--);
}
}
__result = list;
return false;
}
}
[HarmonyPatch(typeof(DuplicateMergeSequencer), "OnSlotSelected", new Type[] { typeof(MainInputInteractable) })]
public class DuplicateMergeSequencer_OnSlotSelected
{
public static bool Prefix(DuplicateMergeSequencer __instance, MainInputInteractable slot)
{
if (!Configs.DuplicateMergeOverrideEnabled)
{
return true;
}
Transform val = ((Component)__instance).transform.Find("CustomCancelButton");
if ((Object)(object)val == (Object)null)
{
return true;
}
ConfirmStoneButton componentInChildren = ((Component)val).GetComponentInChildren<ConfirmStoneButton>(true);
if ((Object)(object)componentInChildren != (Object)null)
{
componentInChildren.Exit();
}
return true;
}
}
[HarmonyPatch(typeof(DuplicateMergeSequencer), "OnSelectionEnded", new Type[] { })]
public class DuplicateMergeSequencer_OnSelectionEnded
{
public static bool Prefix(DuplicateMergeSequencer __instance)
{
if (!Configs.DuplicateMergeOverrideEnabled)
{
return true;
}
Transform val = ((Component)__instance).transform.Find("CustomCancelButton");
if ((Object)(object)val == (Object)null)
{
return true;
}
ConfirmStoneButton componentInChildren = ((Component)val).GetComponentInChildren<ConfirmStoneButton>(true);
if ((Object)(object)componentInChildren != (Object)null)
{
componentInChildren.Enter();
}
return true;
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}