using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using CurseCatcher.Properties;
using HG;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RoR2;
using UnityEngine;
using UnityEngine.Networking;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.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 CurseCatcher.Properties
{
[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[DebuggerNonUserCode]
[CompilerGenerated]
internal class Resources
{
private static ResourceManager resourceMan;
private static CultureInfo resourceCulture;
[EditorBrowsable(EditorBrowsableState.Advanced)]
internal static ResourceManager ResourceManager
{
get
{
if (resourceMan == null)
{
resourceMan = new ResourceManager("CurseCatcher.Properties.Resources", typeof(Resources).Assembly);
}
return resourceMan;
}
}
[EditorBrowsable(EditorBrowsableState.Advanced)]
internal static CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
internal static byte[] disabled => (byte[])ResourceManager.GetObject("disabled", resourceCulture);
internal static byte[] enabled => (byte[])ResourceManager.GetObject("enabled", resourceCulture);
internal Resources()
{
}
}
}
namespace Local.Eclipse.CurseCatcher
{
internal static class Artifact
{
private static ArtifactDef definition = null;
private static int ruleIndex = -1;
[HarmonyPatch(typeof(ArtifactCatalog), "SetArtifactDefs")]
[HarmonyPostfix]
private static void CreateArtifact()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Expected O, but got Unknown
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Expected O, but got Unknown
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Expected O, but got Unknown
definition = new ArtifactDef
{
nameToken = "Artifact of Infliction",
descriptionToken = "Only enemies inflict permanent damage.",
smallIconSelectedSprite = Load(Resources.enabled),
smallIconDeselectedSprite = Load(Resources.disabled),
artifactIndex = (ArtifactIndex)ArtifactCatalog.artifactDefs.Length,
cachedName = "Curse"
};
ArrayUtils.ArrayAppend<ArtifactDef>(ref ArtifactCatalog.artifactDefs, ref definition);
Harmony instance = null;
RunArtifactManager.onArtifactEnabledGlobal += (ArtifactStateChangeDelegate)delegate(RunArtifactManager _, ArtifactDef artifact)
{
if (instance == null && NetworkServer.active && (Object)(object)artifact == (Object)(object)definition)
{
instance = Harmony.CreateAndPatchAll(Plugin.instance.GetType(), (string)null);
}
};
RunArtifactManager.onArtifactDisabledGlobal += (ArtifactStateChangeDelegate)delegate(RunArtifactManager _, ArtifactDef artifact)
{
if ((Object)(object)artifact == (Object)(object)definition)
{
Harmony obj = instance;
if (obj != null)
{
obj.UnpatchSelf();
}
instance = null;
}
};
}
private static Sprite Load(byte[] imageData)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Expected O, but got Unknown
//IL_0034: 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)
Texture2D val = new Texture2D(512, 512, (TextureFormat)5, 4, false);
ImageConversion.LoadImage(val, imageData);
return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2((float)(((Texture)val).width / 2), (float)(((Texture)val).height / 2)));
}
[HarmonyPatch(typeof(RuleCatalog), "Init")]
[HarmonyFinalizer]
private static void AddArtifact(Exception __exception)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
if (__exception != null)
{
throw __exception;
}
RuleDef val = RuleDef.FromArtifact(definition.artifactIndex);
ruleIndex = RuleCatalog.allRuleDefs.Count;
val.globalIndex = ruleIndex;
RuleCatalog.allRuleDefs.Add(val);
RuleCatalog.ruleDefsByGlobalName[val.globalName] = val;
val.category = RuleCatalog.artifactRuleCategory;
RuleCatalog.artifactRuleCategory.children.Add(val);
for (int i = 0; i < val.choices.Count; i++)
{
RuleChoiceDef val2 = val.choices[i];
val2.localIndex = i;
val2.globalIndex = RuleCatalog.allChoicesDefs.Count;
RuleCatalog.allChoicesDefs.Add(val2);
RuleCatalog.ruleChoiceDefsByGlobalName[val2.globalName] = val2;
}
}
[HarmonyPatch(typeof(RuleCatalog), "AddRule")]
[HarmonyPrefix]
private static bool SkipRule(RuleDef ruleDef)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
foreach (RuleChoiceDef choice in ruleDef.choices)
{
if (choice.artifactIndex == definition.artifactIndex)
{
return false;
}
}
return true;
}
[HarmonyPatch(typeof(EclipseRun), "OverrideRuleChoices")]
[HarmonyPostfix]
private static void ShowInEclipse(RuleChoiceMask mustInclude, RuleChoiceMask mustExclude)
{
foreach (RuleChoiceDef item in (IEnumerable<RuleChoiceDef>)((ruleIndex >= 0) ? RuleCatalog.GetRuleDef(ruleIndex).choices : new List<RuleChoiceDef>()))
{
((SerializableBitArray)mustInclude)[item.globalIndex] = false;
((SerializableBitArray)mustExclude)[item.globalIndex] = false;
}
}
[HarmonyPatch(typeof(NetworkExtensions), "Write", new Type[]
{
typeof(NetworkWriter),
typeof(RuleBook)
})]
[HarmonyPrefix]
private static bool WriteRuleBook(NetworkWriter writer, RuleBook src)
{
for (int i = 0; i < src.ruleValues.Length; i++)
{
if (i != ruleIndex)
{
writer.Write(src.ruleValues[i]);
}
}
return false;
}
[HarmonyPatch(typeof(NetworkExtensions), "ReadRuleBook")]
[HarmonyPrefix]
private static bool ReadRuleBook(NetworkReader reader, RuleBook dest)
{
for (int i = 0; i < dest.ruleValues.Length; i++)
{
if (i == ruleIndex)
{
dest.ruleValues[i] = (byte)RuleCatalog.GetRuleDef(ruleIndex).defaultChoiceIndex;
}
else
{
dest.ruleValues[i] = reader.ReadByte();
}
}
return false;
}
[HarmonyPatch(typeof(RunArtifactManager), "OnDeserialize")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> LimitReadLength(IEnumerable<CodeInstruction> IL)
{
MethodInfo readBitArray = typeof(NetworkExtensions).GetMethod("ReadBitArray", new Type[2]
{
typeof(NetworkReader),
typeof(bool[])
});
foreach (CodeInstruction item in IL)
{
if (CodeInstructionExtensions.Calls(item, readBitArray))
{
yield return Transpilers.EmitDelegate<Action<NetworkReader, bool[]>>((Action<NetworkReader, bool[]>)delegate(NetworkReader input, bool[] array)
{
if (definition == null)
{
NetworkExtensions.ReadBitArray(input, array);
}
else
{
NetworkExtensions.ReadBitArray(input, array, array.Length - 1);
}
});
}
else
{
yield return item;
}
}
}
}
[BepInPlugin("local.eclipse.cursecatcher", "CurseCatcher", "0.3.2")]
internal class Plugin : BaseUnityPlugin
{
internal interface IPatch
{
object GetDamageType(DamageInfo info);
}
private class Hopoo : IPatch
{
[HarmonyPatch(typeof(HealthComponent), "TakeDamage")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> Transpile(IEnumerable<CodeInstruction> IL)
{
return InsertCodeInstruction(IL);
}
public object GetDamageType(DamageInfo info)
{
return typeof(DamageInfo).GetField("damageType").GetValue(info);
}
}
private class Gearbox : IPatch
{
[HarmonyPatch(typeof(HealthComponent), "TakeDamageProcess")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> Transpile(IEnumerable<CodeInstruction> IL)
{
return InsertCodeInstruction(IL);
}
public object GetDamageType(DamageInfo info)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Expected I4, but got Unknown
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
DamageType damageType = info.damageType.damageType;
if ((int)damageType != 0)
{
return damageType;
}
return (uint)(int)info.damageType.damageTypeExtended;
}
}
public const string identifier = "local.eclipse.cursecatcher";
public const string version = "0.3.2";
private static bool artifact;
private static ConfigEntry<bool> self;
private static ConfigEntry<bool> friendly;
private static ConfigEntry<bool> fall;
private static ConfigEntry<bool> interactable;
private static ConfigEntry<bool> hazard;
private static ConfigEntry<bool> log;
internal static IPatch instance;
protected void Awake()
{
self = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Self Damage", false, "Abilities that cost health to activate will curse the player if this setting is enabled.");
friendly = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Friendly Fire", true, "Effects that damage allies may apply curse when enabled.");
fall = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Fall Damage", true, "Inflict curse upon taking sufficient fall damage.");
interactable = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Interactable Cost", true, "Whether the debuff is triggered upon paying health costs.");
hazard = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Neutral Hazards", true, "If neutral damage, such as stage hazards, can cause curse.");
artifact = ((BaseUnityPlugin)this).Config.Bind<bool>("Other", "Artifact Enabled", false, "Used to toggle the above functionality. Selectable in the Eclipse lobby, but also applies the modifier to other game modes.").Value;
log = ((BaseUnityPlugin)this).Config.Bind<bool>("Other", "Detailed Logging", false, "For troubleshooting purposes only.");
if (artifact)
{
Harmony.CreateAndPatchAll(typeof(Artifact), (string)null);
RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(CheckVersion));
return;
}
RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, (Action)delegate
{
CheckVersion();
Harmony.CreateAndPatchAll(instance.GetType(), (string)null);
});
}
private void CheckVersion()
{
IPatch patch2;
if (!Version.TryParse(RoR2Application.GetBuildId(), out Version result) || !(result < new Version(1, 3)))
{
IPatch patch = new Gearbox();
patch2 = patch;
}
else
{
IPatch patch = new Hopoo();
patch2 = patch;
}
instance = patch2;
}
private static IEnumerable<CodeInstruction> InsertCodeInstruction(IEnumerable<CodeInstruction> IL)
{
MethodInfo getSelectedDifficulty = typeof(Run).GetProperty("selectedDifficulty").GetMethod;
bool found = false;
CodeInstruction previousInstruction = null;
Console.WriteLine("Installing hook for 'Eclipse 8' curse...");
Label? label = default(Label?);
foreach (CodeInstruction instruction in IL)
{
if (found && CodeInstructionExtensions.Branches(instruction, ref label))
{
found = false;
if (CodeInstructionExtensions.LoadsConstant(previousInstruction, (Enum)(object)(DifficultyIndex)10))
{
Console.WriteLine("...instruction sequence found.");
yield return new CodeInstruction(OpCodes.Pop, (object)null);
yield return new CodeInstruction(OpCodes.Ldarg_1, (object)null);
yield return CodeInstruction.Call(typeof(Plugin), "ApplyCurse", (Type[])null, (Type[])null);
yield return new CodeInstruction(OpCodes.Brfalse, instruction.operand);
continue;
}
}
else if (CodeInstructionExtensions.Calls(instruction, getSelectedDifficulty))
{
found = true;
}
previousInstruction = instruction;
yield return instruction;
}
}
public static bool ApplyCurse(DifficultyIndex difficulty, DamageInfo damageInfo)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Invalid comparison between Unknown and I4
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Invalid comparison between Unknown and I4
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Invalid comparison between Unknown and I4
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Invalid comparison between Unknown and I4
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
if (!artifact && (int)difficulty < 10)
{
return false;
}
bool flag = true;
if (log.Value)
{
PrintInfo(damageInfo);
}
if (damageInfo.attacker == null)
{
object damageType = instance.GetDamageType(damageInfo);
if (damageType is DamageType val)
{
if ((int)val == 1 || (int)val == 3)
{
goto IL_006a;
}
if (((Enum)val).HasFlag((Enum)(object)(DamageType)2097152))
{
flag = fall.Value;
}
}
else if (damageType is uint && (uint)damageType == 134217728)
{
goto IL_006a;
}
}
else if (Object.op_Implicit((Object)(object)damageInfo.attacker))
{
TeamComponent component = damageInfo.attacker.GetComponent<TeamComponent>();
if (Object.op_Implicit((Object)(object)component))
{
TeamIndex teamIndex = component.teamIndex;
if ((int)teamIndex != 0)
{
if ((int)teamIndex == 1)
{
flag = friendly.Value;
}
}
else
{
flag = hazard.Value;
}
}
else if (damageInfo.attacker.GetComponent<IInteractable>() != null)
{
flag = interactable.Value;
}
}
goto IL_0102;
IL_0102:
if (flag)
{
return true;
}
if (log.Value)
{
Console.WriteLine("...preventing curse.");
}
return false;
IL_006a:
flag = self.Value;
goto IL_0102;
}
private static void PrintInfo(DamageInfo damage)
{
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: 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)
string text = getName(damage.attacker);
string text2 = getName(damage.inflictor);
string text3 = "attacker: " + text;
if (text2 != text && damage.inflictor != null)
{
text3 = text3 + " (" + text2 + ")";
}
if ((Object)(object)damage.attacker != (Object)null)
{
TeamComponent component = damage.attacker.GetComponent<TeamComponent>();
if ((Object)(object)component != (Object)null)
{
string text4 = text3;
TeamIndex teamIndex = component.teamIndex;
text3 = text4 + ", team: " + ((object)(TeamIndex)(ref teamIndex)).ToString();
}
}
string text5 = text3;
DamageTypeCombo damageType = damage.damageType;
text3 = text5 + ", type: " + ((object)(DamageTypeCombo)(ref damageType)).ToString();
Console.WriteLine(text3);
static string getName(GameObject obj)
{
string text6 = ((obj == null) ? "null" : (((Object)(object)obj == (Object)null) ? "destroyed" : ((((Object)obj).name != null) ? ((Object)obj).name : "unknown")));
int num = text6.IndexOf('(');
int num2 = text6.IndexOf(')') - num + 1;
if (num >= 0 && num2 >= 0)
{
text6 = text6.Remove(num, num2);
}
return text6;
}
}
}
}