Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of VoidStance v1.0.0
VoidStance.dll
Decompiled 9 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Logging; using EntityStates; using Microsoft.CodeAnalysis; using On.RoR2; using R2API; using R2API.Utils; using RoR2; using RoR2.Skills; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: NetworkCompatibility(/*Could not decode attribute arguments.*/)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("VoidStance")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+71d41ee0805864580ef5297067384fa6cd5f7753")] [assembly: AssemblyProduct("VoidStance")] [assembly: AssemblyTitle("VoidStance")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [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 VoidStanceMod { [BepInPlugin("com.MyName.VoidStance", "VoidStance", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public class VoidStanceToggle : BaseSkillState { public override void OnEnter() { ((BaseState)this).OnEnter(); CharacterBody characterBody = ((EntityState)this).characterBody; if (characterBody != null) { characterBody.SetAimTimer(0.2f); } ((EntityState)this).PlayCrossfade("Gesture, Additive", "BufferEmpty", "BufferEmpty.playbackRate", 0.1f, 0.05f); if (!Object.op_Implicit((Object)(object)((EntityState)this).characterBody)) { return; } VoidStanceController voidStanceController = ((Component)((EntityState)this).characterBody).GetComponent<VoidStanceController>(); if (!Object.op_Implicit((Object)(object)voidStanceController)) { voidStanceController = ((Component)((EntityState)this).characterBody).gameObject.AddComponent<VoidStanceController>(); } if (!NetworkServer.active) { VoidStanceNet component = ((Component)((EntityState)this).characterBody).GetComponent<VoidStanceNet>(); if ((Object)(object)component != (Object)null) { component.RequestToggle(); return; } ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[VoidStance] Net component missing on client."); } } else { ServerToggleNow(voidStanceController); } } private void ServerToggleNow(VoidStanceController ctrl) { ctrl.ResolveAndBindController(); if (ctrl.LockedIsHigh()) { ctrl.GoControlledNow(); } else { ctrl.GoCorruptedNow(); } } public override void FixedUpdate() { ((EntityState)this).FixedUpdate(); if (((EntityState)this).fixedAge >= 0.2f) { ((EntityState)this).outer.SetNextStateToMain(); } } public override InterruptPriority GetMinimumInterruptPriority() { return (InterruptPriority)1; } } public const string PluginGUID = "com.MyName.VoidStance"; public const string PluginName = "VoidStance"; public const string PluginVer = "1.0.0"; internal static ManualLogSource Log; internal static SkillDef StanceSkillDef; private string _pluginDir; private Sprite _modIcon; private Sprite _specialIcon; private void Awake() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; _pluginDir = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); _modIcon = LoadSprite("icon.png"); _specialIcon = LoadSprite("icon_special.png"); bool flag = default(bool); ContentAddition.AddEntityState<VoidStanceToggle>(ref flag); StanceSkillDef = ScriptableObject.CreateInstance<SkillDef>(); StanceSkillDef.skillName = "VOIDSTANCE_TOGGLE"; StanceSkillDef.skillNameToken = "VOIDSTANCE_TOGGLE_NAME"; StanceSkillDef.skillDescriptionToken = "VOIDSTANCE_TOGGLE_DESC"; StanceSkillDef.icon = (((Object)(object)_specialIcon != (Object)null) ? _specialIcon : _modIcon); StanceSkillDef.activationState = new SerializableEntityStateType(typeof(VoidStanceToggle)); StanceSkillDef.activationStateMachineName = "Weapon"; StanceSkillDef.baseMaxStock = 1; StanceSkillDef.rechargeStock = 1; StanceSkillDef.baseRechargeInterval = 2f; StanceSkillDef.beginSkillCooldownOnSkillEnd = true; StanceSkillDef.canceledFromSprinting = false; StanceSkillDef.cancelSprintingOnActivation = false; StanceSkillDef.fullRestockOnAssign = true; StanceSkillDef.isCombatSkill = true; StanceSkillDef.interruptPriority = (InterruptPriority)0; StanceSkillDef.mustKeyPress = true; StanceSkillDef.requiredStock = 1; StanceSkillDef.resetCooldownTimerOnUse = false; ContentAddition.AddSkillDef(StanceSkillDef); LanguageAPI.Add("VOIDSTANCE_TOGGLE_NAME", "Void Stance"); LanguageAPI.Add("VOIDSTANCE_TOGGLE_DESC", "Toggle between Controlled and Corrupted at will. Prevents passive corruption drift and auto-transforms."); RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(InjectIntoVoidFiend)); CharacterBody.onBodyStartGlobal += TryAttachControllers; CharacterBody.Start += new hook_Start(HookBodyStartAttach); Log.LogInfo((object)"[VoidStance] Loaded 1.3.3"); } private Sprite LoadSprite(string fileName) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) try { if (string.IsNullOrEmpty(_pluginDir)) { return null; } string path = Path.Combine(_pluginDir, fileName); if (!File.Exists(path)) { return null; } byte[] array = File.ReadAllBytes(path); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, array)) { return null; } ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[VoidStance] LoadSprite failed for '" + fileName + "': " + ex.Message)); } return null; } } private void InjectIntoVoidFiend() { //IL_0007: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/DLC1/VoidSurvivor/VoidSurvivorBody.prefab").WaitForCompletion(); if (!Object.op_Implicit((Object)(object)val)) { Log.LogError((object)"[VoidStance] Could not load VoidSurvivorBody."); return; } SkillLocator component = val.GetComponent<SkillLocator>(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.special) || !Object.op_Implicit((Object)(object)component.special.skillFamily)) { Log.LogError((object)"[VoidStance] Void Fiend special family not found."); return; } SkillFamily skillFamily = component.special.skillFamily; if (!skillFamily.variants.Any((Variant v) => (Object)(object)v.skillDef == (Object)(object)StanceSkillDef)) { Array.Resize(ref skillFamily.variants, skillFamily.variants.Length + 1); Variant[] variants = skillFamily.variants; int num = variants.Length - 1; Variant val2 = new Variant { skillDef = StanceSkillDef, unlockableDef = null }; ((Variant)(ref val2)).viewableNode = new Node(StanceSkillDef.skillNameToken, false, (Node)null); variants[num] = val2; } Log.LogInfo((object)"[VoidStance] Added 'Void Stance' to Void Fiend Special."); } catch (Exception ex) { Log.LogError((object)("[VoidStance] Injection failed: " + ex)); } } private void HookBodyStartAttach(orig_Start orig, CharacterBody self) { orig.Invoke(self); TryAttachControllers(self); } private void TryAttachControllers(CharacterBody body) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)body)) { return; } if ((!Object.op_Implicit((Object)(object)((Component)body).gameObject) || ((Object)((Component)body).gameObject).name.IndexOf("VoidSurvivor", StringComparison.OrdinalIgnoreCase) < 0) && (string.IsNullOrEmpty(body.baseNameToken) || body.baseNameToken.IndexOf("VOID_SURVIVOR", StringComparison.OrdinalIgnoreCase) < 0)) { string bodyName = BodyCatalog.GetBodyName(body.bodyIndex); if (bodyName == null || bodyName.IndexOf("VoidSurvivor", StringComparison.OrdinalIgnoreCase) < 0) { return; } } if (!Object.op_Implicit((Object)(object)((Component)body).GetComponent<VoidStanceController>())) { ((Component)body).gameObject.AddComponent<VoidStanceController>(); } if (!Object.op_Implicit((Object)(object)((Component)body).GetComponent<VoidStanceNet>())) { ((Component)body).gameObject.AddComponent<VoidStanceNet>(); } } } public class VoidStanceNet : NetworkBehaviour { private CharacterBody body; private VoidStanceController ctrl; private void Awake() { body = ((Component)this).GetComponent<CharacterBody>(); ctrl = ((Component)this).GetComponent<VoidStanceController>(); } public void RequestToggle() { if (!((NetworkBehaviour)this).isServer) { CmdToggle(); } else { ServerToggle(); } } [Command] private void CmdToggle() { ServerToggle(); } private void ServerToggle() { if (!Object.op_Implicit((Object)(object)ctrl)) { ctrl = ((Component)this).GetComponent<VoidStanceController>(); } if (Object.op_Implicit((Object)(object)ctrl)) { ctrl.ResolveAndBindController(); if (ctrl.LockedIsHigh()) { ctrl.GoControlledNow(); } else { ctrl.GoCorruptedNow(); } TargetOnToggled(((NetworkBehaviour)this).connectionToClient, ctrl.LockedIsHigh()); } } [TargetRpc] private void TargetOnToggled(NetworkConnection target, bool isCorrupted) { } } public class VoidStanceController : MonoBehaviour { private CharacterBody body; private GenericSkill special; private Component vfController; private Transform boundTransform; private FieldInfo fldCorruption; private PropertyInfo propCorruption; private FieldInfo fldIsCorrupted; private FieldInfo fldCorruptionActive; private FieldInfo fldMinThreshold; private FieldInfo fldMaxThreshold; private FieldInfo[] corruptionRelatedFloats; private MethodInfo mEnterCorruption; private MethodInfo mExitCorruption; private MethodInfo mSetCorruptionActiveBool; private MethodInfo mTryTransformToCorrupted; private MethodInfo mTryTransformToBase; private MethodInfo mRequestTransformationBool; private float lockedCorruption = float.NaN; private bool corruptionIsPercent = true; private bool userChoseStance; private bool overrideApplied; private float rebindTick; private bool dumped; private void Start() { body = ((Component)this).GetComponent<CharacterBody>(); CharacterBody obj = body; special = ((obj == null) ? null : obj.skillLocator?.special); userChoseStance = HasVoidStanceSelected(); ResolveAndBindController(); SnapLockValue(); } private void OnDestroy() { TryUnsetOverride(); } private bool HasVoidStanceSelected() { if (!Object.op_Implicit((Object)(object)special) || (Object)(object)Plugin.StanceSkillDef == (Object)null) { return false; } return (Object)(object)special.skillDef == (Object)(object)Plugin.StanceSkillDef; } private bool FamilyContainsOurDef() { if (!Object.op_Implicit((Object)(object)special) || (Object)(object)special.skillFamily == (Object)null || (Object)(object)Plugin.StanceSkillDef == (Object)null) { return false; } SkillFamily skillFamily = special.skillFamily; for (int i = 0; i < skillFamily.variants.Length; i++) { if ((Object)(object)skillFamily.variants[i].skillDef == (Object)(object)Plugin.StanceSkillDef) { return true; } } return false; } private void TryApplyOverride() { if (!overrideApplied && Object.op_Implicit((Object)(object)special) && !((Object)(object)Plugin.StanceSkillDef == (Object)null) && FamilyContainsOurDef()) { special.SetSkillOverride((object)body, Plugin.StanceSkillDef, (SkillOverridePriority)4); overrideApplied = true; } } private void TryUnsetOverride() { if (overrideApplied) { if (!Object.op_Implicit((Object)(object)special) || (Object)(object)Plugin.StanceSkillDef == (Object)null) { overrideApplied = false; return; } special.UnsetSkillOverride((object)body, Plugin.StanceSkillDef, (SkillOverridePriority)4); overrideApplied = false; } } public void ForceDump() { DumpAllComponents(); } private void FixedUpdate() { rebindTick -= Time.fixedDeltaTime; if (rebindTick <= 0f) { rebindTick = 0.1f; if (!Object.op_Implicit((Object)(object)vfController)) { ResolveAndBindController(); } } if (HasVoidStanceSelected()) { userChoseStance = true; } if (userChoseStance) { TryApplyOverride(); } else { TryUnsetOverride(); } if (NetworkServer.active && Object.op_Implicit((Object)(object)vfController) && userChoseStance) { StrongLockCorruption(); } } private void Update() { if (NetworkServer.active && Object.op_Implicit((Object)(object)vfController) && userChoseStance) { StrongLockCorruption(); } } public bool LockedIsHigh() { if (float.IsNaN(lockedCorruption)) { lockedCorruption = ReadCorruption(); } float num = (float.IsNaN(lockedCorruption) ? 0f : lockedCorruption); return num > (corruptionIsPercent ? 50f : 0.5f); } public void GoCorruptedNow() { ResolveAndBindController(); if (HasVoidStanceSelected()) { userChoseStance = true; } if (userChoseStance) { TryApplyOverride(); } SafeInvoke(mSetCorruptionActiveBool, vfController, new object[1] { false }); SafeInvoke(mEnterCorruption, vfController, null); SafeInvoke(mTryTransformToCorrupted, vfController, null); SafeInvoke(mRequestTransformationBool, vfController, new object[1] { true }); SafeWriteBool(fldIsCorrupted, vfController, v: true); SafeWriteBool(fldCorruptionActive, vfController, v: false); lockedCorruption = (corruptionIsPercent ? 100f : 1f); WriteCorruption(lockedCorruption); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[VoidStance] -> Corrupted"); } } public void GoControlledNow() { ResolveAndBindController(); if (HasVoidStanceSelected()) { userChoseStance = true; } if (userChoseStance) { TryApplyOverride(); } SafeInvoke(mSetCorruptionActiveBool, vfController, new object[1] { false }); SafeInvoke(mExitCorruption, vfController, null); SafeInvoke(mTryTransformToBase, vfController, null); SafeInvoke(mRequestTransformationBool, vfController, new object[1] { false }); SafeWriteBool(fldIsCorrupted, vfController, v: false); SafeWriteBool(fldCorruptionActive, vfController, v: false); lockedCorruption = 0f; WriteCorruption(lockedCorruption); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[VoidStance] -> Controlled"); } } public void ResolveAndBindController() { vfController = null; boundTransform = null; fldCorruption = null; propCorruption = null; fldIsCorrupted = null; fldCorruptionActive = null; fldMinThreshold = null; fldMaxThreshold = null; corruptionRelatedFloats = null; mEnterCorruption = null; mExitCorruption = null; mSetCorruptionActiveBool = null; mTryTransformToCorrupted = null; mTryTransformToBase = null; mRequestTransformationBool = null; if (!Object.op_Implicit((Object)(object)body)) { return; } List<Transform> list = new List<Transform> { body.transform }; ModelLocator modelLocator = body.modelLocator; if (Object.op_Implicit((Object)(object)modelLocator) && Object.op_Implicit((Object)(object)modelLocator.modelTransform)) { list.Add(modelLocator.modelTransform); } if (Object.op_Implicit((Object)(object)modelLocator) && Object.op_Implicit((Object)(object)modelLocator.modelBaseTransform)) { list.Add(modelLocator.modelBaseTransform); } if (Object.op_Implicit((Object)(object)body.masterObject)) { list.Add(body.masterObject.transform); } foreach (Transform item in list.Where((Transform x) => Object.op_Implicit((Object)(object)x))) { Component[] componentsInChildren = ((Component)item).GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val) && ((object)val).GetType().Name.Equals("VoidSurvivorController", StringComparison.OrdinalIgnoreCase) && BindFromComponent(val)) { return; } } } foreach (Transform item2 in list.Where((Transform x) => Object.op_Implicit((Object)(object)x))) { Component[] componentsInChildren2 = ((Component)item2).GetComponentsInChildren<Component>(true); foreach (Component val2 in componentsInChildren2) { if (Object.op_Implicit((Object)(object)val2)) { Type type = ((object)val2).GetType(); if (HasAnyMethod(type, new string[10] { "EnterCorruption", "EnterCorrupted", "StartCorruption", "ExitCorruption", "ExitCorrupted", "StopCorruption", "SetCorruptionActive", "TryTransformToCorrupted", "TryTransformToBase", "RequestTransformation" }) && BindFromComponent(val2)) { return; } } } } foreach (Transform item3 in list.Where((Transform x) => Object.op_Implicit((Object)(object)x))) { Component[] componentsInChildren3 = ((Component)item3).GetComponentsInChildren<Component>(true); foreach (Component val3 in componentsInChildren3) { if (Object.op_Implicit((Object)(object)val3) && HasPlausibleCorruptionValue(val3, out var _, out var _) && BindFromComponent(val3)) { return; } } } if (!dumped) { dumped = true; DumpAllComponents(); } } private bool BindFromComponent(Component c) { vfController = c; boundTransform = c.transform; Type type = ((object)c).GetType(); fldCorruption = FirstField(type, typeof(float), new string[5] { "corruption", "corruptionFrac", "corruptionFraction", "corruptionPercent", "corruptionValue" }) ?? GuessCorruptionFloatField(type, c); if (fldCorruption == null) { propCorruption = FirstProperty(type, typeof(float), new string[4] { "Corruption", "CorruptionFraction", "CorruptionPercent", "Value" }); } fldIsCorrupted = FirstField(type, typeof(bool), new string[4] { "isCorrupted", "isCorruption", "corrupted", "isInCorruptedMode" }); fldCorruptionActive = FirstField(type, typeof(bool), new string[3] { "corruptionActive", "isCorruptionActive", "isCorruptionOn" }); fldMinThreshold = FirstField(type, typeof(float), new string[3] { "minCorruptionToTransform", "minCorruptionToActivate", "minCorruption" }); fldMaxThreshold = FirstField(type, typeof(float), new string[3] { "maxCorruptionToRevert", "maxCorruptionToDeactivate", "maxCorruption" }); FieldInfo[] array = (from f in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where f.FieldType == typeof(float) select f).ToArray(); List<FieldInfo> list = new List<FieldInfo>(); FieldInfo[] array2 = array; foreach (FieldInfo fieldInfo in array2) { string text = fieldInfo.Name.ToLowerInvariant(); if (text.Contains("corrupt") && ShouldZero(fieldInfo)) { list.Add(fieldInfo); } } corruptionRelatedFloats = list.ToArray(); mEnterCorruption = FirstMethod(type, new string[3] { "EnterCorruption", "EnterCorrupted", "StartCorruption" }, Type.EmptyTypes); mExitCorruption = FirstMethod(type, new string[3] { "ExitCorruption", "ExitCorrupted", "StopCorruption" }, Type.EmptyTypes); mSetCorruptionActiveBool = FirstMethod(type, new string[2] { "SetCorruptionActive", "SetCorrupted" }, new Type[1] { typeof(bool) }); mTryTransformToCorrupted = FirstMethod(type, new string[2] { "TryTransformToCorrupted", "TryEnterCorruption" }, Type.EmptyTypes); mTryTransformToBase = FirstMethod(type, new string[2] { "TryTransformToBase", "TryExitCorruption" }, Type.EmptyTypes); mRequestTransformationBool = FirstMethod(type, new string[2] { "RequestTransformation", "RequestCorruption" }, new Type[1] { typeof(bool) }); float num = ReadCorruption(); if (!float.IsNaN(num)) { corruptionIsPercent = num > 1.0001f && num <= 100f; } else { corruptionIsPercent = false; } ManualLogSource log = Plugin.Log; if (log != null) { object[] obj = new object[4] { type.FullName, PathOf(boundTransform), fldCorruption?.Name ?? propCorruption?.Name ?? "<?>", null }; FieldInfo[] array3 = corruptionRelatedFloats; obj[3] = ((array3 != null) ? array3.Length : 0); log.LogInfo((object)string.Format("[VoidStance] Bound: {0} @ {1} | value={2} | floatsToZero={3}", obj)); } return true; bool ShouldZero(FieldInfo f) { string text2 = f.Name.ToLowerInvariant(); if (fldCorruption != null && f == fldCorruption) { return false; } if (text2.Contains("min") || text2.Contains("max") || text2.Contains("threshold") || text2.Contains("limit") || text2.Contains("bound")) { return false; } if (text2.Contains("toactivate") || text2.Contains("totransform")) { return false; } if (text2.EndsWith("percent") || text2.EndsWith("fraction") || text2.EndsWith("value")) { return false; } return text2.Contains("rate") || text2.Contains("drift") || text2.Contains("delta") || text2.Contains("speed") || text2.Contains("gain") || text2.Contains("loss") || text2.Contains("regen") || text2.Contains("persecond"); } } private void StrongLockCorruption() { if (float.IsNaN(lockedCorruption)) { lockedCorruption = ReadCorruption(); } if (float.IsNaN(lockedCorruption)) { lockedCorruption = 0f; } if (corruptionIsPercent) { lockedCorruption = Mathf.Clamp(lockedCorruption, 0f, 100f); } else { lockedCorruption = Mathf.Clamp01(lockedCorruption); } WriteCorruption(lockedCorruption); SafeInvoke(mSetCorruptionActiveBool, vfController, new object[1] { false }); if (corruptionRelatedFloats != null) { for (int i = 0; i < corruptionRelatedFloats.Length; i++) { SafeWriteFloat(corruptionRelatedFloats[i], vfController, 0f); } } } private void DumpAllComponents() { try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("=== VoidStance Component Dump ==="); CharacterBody obj = body; ModelLocator val = ((obj != null) ? obj.modelLocator : null); List<Transform> list = new List<Transform>(); if (Object.op_Implicit((Object)(object)body)) { list.Add(body.transform); } if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.modelTransform)) { list.Add(val.modelTransform); } if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.modelBaseTransform)) { list.Add(val.modelBaseTransform); } if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.masterObject)) { list.Add(body.masterObject.transform); } foreach (Transform item in list.Where((Transform x) => Object.op_Implicit((Object)(object)x))) { stringBuilder.AppendLine("-- ROOT: " + PathOf(item)); Component[] componentsInChildren = ((Component)item).GetComponentsInChildren<Component>(true); foreach (Component val2 in componentsInChildren) { if (Object.op_Implicit((Object)(object)val2)) { Type type = ((object)val2).GetType(); stringBuilder.AppendLine(" " + PathOf(val2.transform) + " :: " + type.FullName); if (HasAnyMethod(type, new string[6] { "EnterCorruption", "ExitCorruption", "SetCorruptionActive", "TryTransformToCorrupted", "TryTransformToBase", "RequestTransformation" })) { stringBuilder.AppendLine(" [*] has corruption methods"); } if (HasPlausibleCorruptionValue(val2, out var fOut, out var pOut)) { stringBuilder.AppendLine(" [*] has corruption value via " + ((fOut != null) ? ("field:" + fOut.Name) : ("prop:" + pOut.Name))); } } } } string text = Path.Combine(Paths.BepInExRootPath, "LogOutput"); Directory.CreateDirectory(text); string text2 = Path.Combine(text, "VoidStance.dump.txt"); File.WriteAllText(text2, stringBuilder.ToString()); ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[VoidStance] Dump written: " + text2)); } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[VoidStance] Dump failed: " + ex.Message)); } } } private static bool HasAnyMethod(Type t, IEnumerable<string> names) { foreach (string name in names) { if (t.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null) { return true; } } return false; } private static bool HasPlausibleCorruptionValue(Component c, out FieldInfo fOut, out PropertyInfo pOut) { fOut = null; pOut = null; Type type = ((object)c).GetType(); FieldInfo fieldInfo = FirstField(type, typeof(float), new string[5] { "corruption", "corruptionFraction", "corruptionFrac", "corruptionPercent", "corruptionValue" }) ?? GuessCorruptionFloatField(type, c); PropertyInfo propertyInfo = null; if (fieldInfo == null) { propertyInfo = FirstProperty(type, typeof(float), new string[4] { "Corruption", "CorruptionFraction", "CorruptionPercent", "Value" }); } float num = float.NaN; try { if (fieldInfo != null) { num = (float)fieldInfo.GetValue(c); } else if (propertyInfo != null) { num = (float)propertyInfo.GetValue(c, null); } } catch { } if (!float.IsNaN(num) && ((num >= 0f && num <= 1f) || (num >= 0f && num <= 100f))) { fOut = fieldInfo; pOut = propertyInfo; return true; } return false; } private static FieldInfo FirstField(Type t, Type ft, IEnumerable<string> names) { foreach (string name in names) { FieldInfo field = t.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == ft) { return field; } } return null; } private static PropertyInfo FirstProperty(Type t, Type pt, IEnumerable<string> names) { foreach (string name in names) { PropertyInfo property = t.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == pt && property.CanRead && property.CanWrite) { return property; } } return null; } private static MethodInfo FirstMethod(Type t, IEnumerable<string> names, Type[] sig) { foreach (string name in names) { MethodInfo method = t.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, sig, null); if (method != null) { return method; } } return null; } private static MethodInfo FirstMethod(Type t, IEnumerable<string> names, Type emptySig) { return FirstMethod(t, names, Type.EmptyTypes); } private static FieldInfo GuessCorruptionFloatField(Type t, object inst) { try { FieldInfo[] array = (from f in t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where f.FieldType == typeof(float) select f).ToArray(); FieldInfo[] array2 = array.Where((FieldInfo f) => f.Name.IndexOf("corrupt", StringComparison.OrdinalIgnoreCase) >= 0).ToArray(); FieldInfo[] array3 = ((array2.Length != 0) ? array2 : array); FieldInfo[] array4 = array3; foreach (FieldInfo fieldInfo in array4) { try { float num = (float)fieldInfo.GetValue(inst); if ((num >= 0f && num <= 1f) || (num >= 0f && num <= 100f)) { return fieldInfo; } } catch { } } } catch { } return null; } private float ReadCorruption() { try { if (fldCorruption != null) { return (float)fldCorruption.GetValue(vfController); } if (propCorruption != null) { return (float)propCorruption.GetValue(vfController, null); } } catch { } return float.NaN; } private void WriteCorruption(float value) { try { if (fldCorruption != null) { fldCorruption.SetValue(vfController, value); } else if (propCorruption != null) { propCorruption.SetValue(vfController, value, null); } } catch { } } private void SafeWriteFloat(FieldInfo f, object o, float v) { if (f == null) { return; } try { f.SetValue(o, v); } catch { } } private void SafeWriteBool(FieldInfo f, object o, bool v) { if (f == null) { return; } try { f.SetValue(o, v); } catch { } } private bool? ReadBool(FieldInfo f, object o) { if (f == null) { return null; } try { return (bool)f.GetValue(o); } catch { return null; } } private bool SafeInvoke(MethodInfo m, object o, object[] args) { if (m == null) { return false; } try { m.Invoke(o, args); return true; } catch { return false; } } private static string PathOf(Transform t) { if (!Object.op_Implicit((Object)(object)t)) { return "<null>"; } List<string> list = new List<string>(); while (Object.op_Implicit((Object)(object)t)) { list.Add(((Object)t).name); t = t.parent; } list.Reverse(); return string.Join("/", list); } private void SnapLockValue() { bool? flag = ReadBool(fldIsCorrupted, vfController); if (flag.HasValue) { lockedCorruption = ((!flag.Value) ? 0f : (corruptionIsPercent ? 100f : 1f)); WriteCorruption(lockedCorruption); return; } float num = ReadCorruption(); if (float.IsNaN(num)) { num = 0f; } if (num < 0f) { num = 0f; } if (num > 100f) { num = 100f; } if (num <= 1.0001f) { corruptionIsPercent = false; } else if (num <= 100f) { corruptionIsPercent = true; } lockedCorruption = num; } } } namespace VoidStance { internal static class Log { private static ManualLogSource _logSource; internal static void Init(ManualLogSource logSource) { _logSource = logSource; } internal static void Debug(object data) { _logSource.LogDebug(data); } internal static void Error(object data) { _logSource.LogError(data); } internal static void Fatal(object data) { _logSource.LogFatal(data); } internal static void Info(object data) { _logSource.LogInfo(data); } internal static void Message(object data) { _logSource.LogMessage(data); } internal static void Warning(object data) { _logSource.LogWarning(data); } } }