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 ComboBrawler v1.0.2
BepInEx/plugins/ComboBrawler.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Events; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ComboBrawler")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+2fc8d9ff94cefe0b70d4c23259b771fda99a9708")] [assembly: AssemblyProduct("ComboBrawler")] [assembly: AssemblyTitle("ComboBrawler")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ComboBrawler { internal static class ClawGlow { private const float Peak = 0.35f; private const float Inflate = 0.01f; private static readonly Color Tint = new Color(0.45f, 0.7f, 1f); private static bool logged; private static readonly Dictionary<Mesh, Mesh> Shells = new Dictionary<Mesh, Mesh>(); private static Shader shader; internal static IEnumerator Run(Character c, float seconds) { yield return null; List<GameObject> made = new List<GameObject>(); List<Material> mats = new List<Material>(); foreach (Renderer item in Sources(c)) { GameObject val = Copy(item, mats); if ((Object)(object)val != (Object)null) { made.Add(val); } } if (made.Count == 0) { yield break; } for (float el = 0f; el < seconds; el += Time.deltaTime) { if (!((Object)(object)c != (Object)null)) { break; } if (c.IsDead()) { break; } float a = WolfMath.GlowAlpha(el, seconds, 0.35f); foreach (Material item2 in mats) { SetTint(item2, a); } yield return null; } foreach (GameObject item3 in made) { if ((Object)(object)item3 != (Object)null) { Object.Destroy((Object)(object)item3); } } foreach (Material item4 in mats) { Object.Destroy((Object)(object)item4); } } private static IEnumerable<Renderer> Sources(Character c) { VisEquipment ve = (((Object)(object)c != (Object)null) ? ((Component)c).GetComponent<VisEquipment>() : null); if ((Object)(object)ve == (Object)null) { yield break; } FieldRef<VisEquipment, GameObject>[] array = new FieldRef<VisEquipment, GameObject>[2] { Refs.RightItemInstance, Refs.LeftItemInstance }; foreach (FieldRef<VisEquipment, GameObject> val in array) { GameObject val2 = ((val != null) ? val.Invoke(ve) : null); if ((Object)(object)val2 == (Object)null) { continue; } Renderer[] componentsInChildren = val2.GetComponentsInChildren<Renderer>(); foreach (Renderer val3 in componentsInChildren) { if (val3 is SkinnedMeshRenderer || val3 is MeshRenderer) { yield return val3; } } } } private static GameObject Copy(Renderer src, List<Material> mats) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Expected O, but got Unknown if ((Object)(object)shader == (Object)null) { shader = Shader.Find("Legacy Shaders/Particles/Additive") ?? Shader.Find("Particles/Additive") ?? Shader.Find("Sprites/Default") ?? Shader.Find("UI/Default"); } if ((Object)(object)shader == (Object)null) { return null; } GameObject val = new GameObject("BrawlClawGlow"); val.transform.SetParent(((Component)src).transform.parent, false); val.transform.localPosition = ((Component)src).transform.localPosition; val.transform.localRotation = ((Component)src).transform.localRotation; val.transform.localScale = ((Component)src).transform.localScale; val.layer = ((Component)src).gameObject.layer; SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((src is SkinnedMeshRenderer) ? src : null); Renderer val3; if (val2 != null) { SkinnedMeshRenderer obj = val.AddComponent<SkinnedMeshRenderer>(); obj.sharedMesh = Shell(val2.sharedMesh, Scale(src, val2.sharedMesh)); obj.bones = val2.bones; obj.rootBone = val2.rootBone; obj.updateWhenOffscreen = true; val3 = (Renderer)(object)obj; } else { MeshFilter component = ((Component)src).GetComponent<MeshFilter>(); if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null) { Object.Destroy((Object)(object)val); return null; } val.AddComponent<MeshFilter>().sharedMesh = Shell(component.sharedMesh, Scale(src, component.sharedMesh)); val3 = (Renderer)(object)val.AddComponent<MeshRenderer>(); } Material val4 = new Material(shader); SetTint(val4, 0f); mats.Add(val4); Material[] array = (Material[])(object)new Material[Mathf.Max(1, src.sharedMaterials.Length)]; for (int i = 0; i < array.Length; i++) { array[i] = val4; } val3.sharedMaterials = array; val3.shadowCastingMode = (ShadowCastingMode)0; val3.receiveShadows = false; return val; } private static void SetTint(Material m, float a) { //IL_006f: 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) if (m.HasProperty("_TintColor")) { m.SetColor("_TintColor", new Color(Tint.r * 0.5f, Tint.g * 0.5f, Tint.b * 0.5f, a)); } else { m.color = new Color(Tint.r, Tint.g, Tint.b, a); } } private static float Scale(Renderer r, Mesh mesh) { //IL_0010: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0035: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mesh == (Object)null) { return 1f; } Bounds bounds = mesh.bounds; Vector3 size = ((Bounds)(ref bounds)).size; float magnitude = ((Vector3)(ref size)).magnitude; bounds = r.bounds; size = ((Bounds)(ref bounds)).size; float magnitude2 = ((Vector3)(ref size)).magnitude; float num = ((magnitude > 1E-06f && magnitude2 > 1E-06f) ? (magnitude2 / magnitude) : 1f); if (!logged) { logged = true; Plugin.Log.LogInfo((object)$"Claw outline: shader {((Object)shader).name}, mesh {((Object)mesh).name} readable {mesh.isReadable}, world/mesh scale {num:0.###}"); } return num; } private static Mesh Shell(Mesh src, float scale) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)src == (Object)null || !src.isReadable) { return src; } if (Shells.TryGetValue(src, out var value) && (Object)(object)value != (Object)null) { return value; } Mesh val = Object.Instantiate<Mesh>(src); Vector3[] vertices = val.vertices; Vector3[] normals = val.normals; float num = 0.01f / Mathf.Max(1E-06f, scale); if (normals != null && normals.Length == vertices.Length) { for (int i = 0; i < vertices.Length; i++) { ref Vector3 reference = ref vertices[i]; reference += normals[i] * num; } val.vertices = vertices; val.RecalculateBounds(); } Shells[src] = val; return val; } } internal static class ClipSets { private class Own { public AnimatorOverrideController Controller; public RuntimeAnimatorController Base; } internal const string BundleFile = "combobrawler.bundle"; private static AssetBundle bundle; private static bool bundleTried; private static Stream embeddedBundleStream; private static readonly Dictionary<string, AnimationClip> clips = new Dictionary<string, AnimationClip>(); private static readonly ConditionalWeakTable<Animator, Own> own = new ConditionalWeakTable<Animator, Own>(); private static readonly Move[] Moves = new Move[9] { Move.L1, Move.L2, Move.L3, Move.S1, Move.S2, Move.S3, Move.H1, Move.H2, Move.H3 }; internal static AnimationClip Clip(string name) { if (string.IsNullOrEmpty(name)) { return null; } if (clips.TryGetValue(name, out var value)) { return value; } if (!bundleTried) { bundleTried = true; string text = Path.Combine(Plugin.PluginFolder ?? "", "combobrawler.bundle"); if (File.Exists(text)) { bundle = AssetBundle.LoadFromFile(text); Plugin.Log.Log((LogLevel)(Object.op_Implicit((Object)(object)bundle) ? 16 : 4), (object)(Object.op_Implicit((Object)(object)bundle) ? ("Loaded bundle " + text) : ("Bundle found but could not be read: " + text))); } else { bundle = LoadEmbeddedBundle(); Plugin.Log.Log((LogLevel)(Object.op_Implicit((Object)(object)bundle) ? 16 : 4), (object)(Object.op_Implicit((Object)(object)bundle) ? "No bundle file next to the DLL - loaded the embedded copy from this assembly." : ("Bundle not found: " + text + ", and this build has no embedded bundle."))); } } value = (Object.op_Implicit((Object)(object)bundle) ? bundle.LoadAsset<AnimationClip>(name) : null); if ((Object)(object)value == (Object)null) { Plugin.Log.LogWarning((object)("Custom clip '" + name + "' not found in the bundle.")); } else if (!Array.Exists(value.events, (AnimationEvent e) => e.functionName == "OnAttackTrigger")) { Plugin.Log.LogWarning((object)("Custom clip '" + name + "' has no OnAttackTrigger event - it would never hit. Ignoring it.")); value = null; } else { Plugin.Log.LogDebug((object)$"Custom clip '{name}' loaded ({value.length:0.00}s)."); } clips[name] = value; return value; } private static AssetBundle LoadEmbeddedBundle() { try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = null; string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); foreach (string text2 in manifestResourceNames) { if (text2.EndsWith("combobrawler.bundle", StringComparison.OrdinalIgnoreCase)) { text = text2; break; } } if (text == null) { return null; } using Stream stream = executingAssembly.GetManifestResourceStream(text); if (stream == null) { return null; } MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); memoryStream.Position = 0L; embeddedBundleStream = memoryStream; return AssetBundle.LoadFromStream((Stream)memoryStream); } catch (Exception ex) { Plugin.Log.LogError((object)("Could not load the embedded bundle (" + ex.GetType().Name + ": " + ex.Message + ").")); return null; } } private static Dictionary<string, AnimationClip> Pairs(Style? style) { Dictionary<string, AnimationClip> dictionary = new Dictionary<string, AnimationClip>(); if (!style.HasValue) { return dictionary; } Move[] moves = Moves; foreach (Move m in moves) { AnimationClip val = Clip(Styles.ClipName(style.Value, m)); if ((Object)(object)val != (Object)null) { dictionary[Styles.HostClip(m)] = val; } } return dictionary; } internal static void Apply(Animator animator, Style? style) { if ((Object)(object)animator == (Object)null) { return; } Dictionary<string, AnimationClip> want = Pairs(style); AnimatorOverrideController aoc = default(AnimatorOverrideController); ref AnimatorOverrideController reference = ref aoc; RuntimeAnimatorController runtimeAnimatorController = animator.runtimeAnimatorController; reference = (AnimatorOverrideController)(object)((runtimeAnimatorController is AnimatorOverrideController) ? runtimeAnimatorController : null); if ((Object)(object)aoc == (Object)null) { if (want.Count == 0) { return; } aoc = Wrap(animator); if ((Object)(object)aoc == (Object)null) { return; } } if (!Matches(aoc, want)) { Preserving(animator, delegate { Write(aoc, want); }); } if (want.Count == 0) { Unwrap(animator); } } internal static bool OursPresent(Animator animator, Style style) { AnimatorOverrideController val = (AnimatorOverrideController)(((Object)(object)animator != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); Dictionary<string, AnimationClip> dictionary = Pairs(style); if ((Object)(object)val != (Object)null && dictionary.Count > 0) { return Matches(val, dictionary); } return false; } private static bool IsHost(string clipName) { Move[] moves = Moves; for (int i = 0; i < moves.Length; i++) { if (Styles.HostClip(moves[i]) == clipName) { return true; } } return false; } private static bool Matches(AnimatorOverrideController aoc, Dictionary<string, AnimationClip> want) { List<KeyValuePair<AnimationClip, AnimationClip>> list = new List<KeyValuePair<AnimationClip, AnimationClip>>(); aoc.GetOverrides(list); foreach (KeyValuePair<AnimationClip, AnimationClip> item in list) { if (!((Object)(object)item.Key == (Object)null) && IsHost(((Object)item.Key).name)) { want.TryGetValue(((Object)item.Key).name, out var value); if ((Object)(object)item.Value != (Object)(object)value) { return false; } } } return true; } private static void Write(AnimatorOverrideController aoc, Dictionary<string, AnimationClip> want) { List<KeyValuePair<AnimationClip, AnimationClip>> list = new List<KeyValuePair<AnimationClip, AnimationClip>>(); aoc.GetOverrides(list); for (int i = 0; i < list.Count; i++) { AnimationClip key = list[i].Key; if (!((Object)(object)key == (Object)null) && IsHost(((Object)key).name)) { want.TryGetValue(((Object)key).name, out var value); list[i] = new KeyValuePair<AnimationClip, AnimationClip>(key, value); } } aoc.ApplyOverrides((IList<KeyValuePair<AnimationClip, AnimationClip>>)list); } private static AnimatorOverrideController Wrap(Animator animator) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown RuntimeAnimatorController runtimeAnimatorController = animator.runtimeAnimatorController; if ((Object)(object)runtimeAnimatorController == (Object)null) { return null; } AnimatorOverrideController controller = new AnimatorOverrideController(runtimeAnimatorController) { name = ((Object)runtimeAnimatorController).name + " (ComboBrawler)" }; Preserving(animator, delegate { animator.runtimeAnimatorController = (RuntimeAnimatorController)(object)controller; }); own.Remove(animator); own.Add(animator, new Own { Controller = controller, Base = runtimeAnimatorController }); return controller; } private static void Unwrap(Animator animator) { if (!own.TryGetValue(animator, out var o)) { return; } if ((Object)(object)animator.runtimeAnimatorController != (Object)(object)o.Controller) { own.Remove(animator); return; } List<KeyValuePair<AnimationClip, AnimationClip>> list = new List<KeyValuePair<AnimationClip, AnimationClip>>(); o.Controller.GetOverrides(list); foreach (KeyValuePair<AnimationClip, AnimationClip> item in list) { if ((Object)(object)item.Value != (Object)null) { return; } } Preserving(animator, delegate { animator.runtimeAnimatorController = o.Base; }); own.Remove(animator); } private static void Preserving(Animator animator, Action change) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected I4, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Expected I4, but got Unknown //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) int layerCount = animator.layerCount; AnimatorStateInfo[] array = (AnimatorStateInfo[])(object)new AnimatorStateInfo[layerCount]; float[] array2 = new float[layerCount]; for (int i = 0; i < layerCount; i++) { array[i] = (animator.IsInTransition(i) ? animator.GetNextAnimatorStateInfo(i) : animator.GetCurrentAnimatorStateInfo(i)); array2[i] = animator.GetLayerWeight(i); } AnimatorControllerParameter[] parameters = animator.parameters; float[] array3 = new float[parameters.Length]; for (int j = 0; j < parameters.Length; j++) { AnimatorControllerParameterType type = parameters[j].type; switch (type - 1) { case 0: array3[j] = animator.GetFloat(parameters[j].nameHash); break; case 2: array3[j] = animator.GetInteger(parameters[j].nameHash); break; case 3: array3[j] = (animator.GetBool(parameters[j].nameHash) ? 1f : 0f); break; } } float speed = animator.speed; change(); animator.Update(0f); for (int k = 0; k < parameters.Length; k++) { AnimatorControllerParameterType type = parameters[k].type; switch (type - 1) { case 0: animator.SetFloat(parameters[k].nameHash, array3[k]); break; case 2: animator.SetInteger(parameters[k].nameHash, (int)array3[k]); break; case 3: animator.SetBool(parameters[k].nameHash, array3[k] != 0f); break; } } for (int l = 0; l < layerCount && l < animator.layerCount; l++) { animator.SetLayerWeight(l, array2[l]); AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(l); if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash != ((AnimatorStateInfo)(ref array[l])).fullPathHash) { animator.Play(((AnimatorStateInfo)(ref array[l])).fullPathHash, l, ((AnimatorStateInfo)(ref array[l])).normalizedTime); } } animator.speed = speed; } } public enum Move { None, L1, L2, L3, S1, S2, S3, H1, H2, H3 } public enum Press { Primary, Special } public static class ComboGraph { public static Move Next(Move current, Press press, bool inWindow) { if (press == Press.Primary) { if (!inWindow) { return Move.L1; } return current switch { Move.L1 => Move.L2, Move.L2 => Move.L3, _ => Move.L1, }; } if (!inWindow) { return Move.H1; } return current switch { Move.L1 => Move.S1, Move.L2 => Move.S2, Move.L3 => Move.S3, Move.H1 => Move.H2, Move.H2 => Move.H3, _ => Move.H1, }; } public static bool ChainsAtChainPoint(Move current, Press press) { if (press == Press.Primary) { if (current != Move.L1) { return current == Move.L2; } return true; } if (current != Move.L1 && current != Move.L2 && current != Move.L3 && current != Move.H1) { return current == Move.H2; } return true; } public static bool IsFinisher(Move m) { if (m != Move.S1 && m != Move.S2) { return m == Move.S3; } return true; } } [DefaultExecutionOrder(10000)] internal class FistHold : MonoBehaviour { private static readonly Dictionary<string, Quaternion> Fist = new Dictionary<string, Quaternion> { ["LeftHandThumb1"] = new Quaternion(0.5547f, -0.2076f, -0.3706f, 0.7155f), ["LeftHandThumb2"] = new Quaternion(-0.2336f, 0.1314f, 0.5942f, 0.7583f), ["LeftHandThumb3"] = new Quaternion(-0.1547f, -0.2399f, 0.3091f, 0.9072f), ["LeftHandIndex1"] = new Quaternion(0.7056f, -0.0774f, -0.0665f, 0.7013f), ["LeftHandIndex2"] = new Quaternion(0.8006f, 0.0915f, 0.0522f, 0.5899f), ["LeftHandIndex3"] = new Quaternion(0.5161f, 0.0075f, 0.0447f, 0.8554f), ["LeftHandMiddle1"] = new Quaternion(0.6958f, -0.0408f, -0.0192f, 0.7168f), ["LeftHandMiddle2"] = new Quaternion(0.8675f, 0.0252f, 0.0296f, 0.4958f), ["LeftHandMiddle3"] = new Quaternion(0.5554f, 0.0339f, 0.0325f, 0.8303f), ["LeftHandRing1"] = new Quaternion(0.6529f, 0.0145f, 0.0278f, 0.7568f), ["LeftHandRing2"] = new Quaternion(0.8177f, -0.0011f, 0.0446f, 0.5739f), ["LeftHandRing3"] = new Quaternion(0.5278f, 0.0084f, 0.0224f, 0.849f), ["LeftHandPinky1"] = new Quaternion(0.6403f, 0.0448f, 0.0765f, 0.763f), ["LeftHandPinky2"] = new Quaternion(0.7099f, -0.0146f, 0.0442f, 0.7028f), ["LeftHandPinky3"] = new Quaternion(0.4321f, -0.0171f, 0.077f, 0.8984f), ["RightHandThumb1"] = new Quaternion(0.6179f, 0.2628f, 0.3265f, 0.6652f), ["RightHandThumb2"] = new Quaternion(-0.4899f, -0.0768f, -0.5109f, 0.7022f), ["RightHandThumb3"] = new Quaternion(0.1296f, 0.2428f, -0.2951f, 0.915f), ["RightHandIndex1"] = new Quaternion(0.7045f, 0.0771f, 0.0665f, 0.7023f), ["RightHandIndex2"] = new Quaternion(0.7994f, -0.0917f, -0.0522f, 0.5915f), ["RightHandIndex3"] = new Quaternion(0.5148f, -0.0075f, -0.0447f, 0.8561f), ["RightHandMiddle1"] = new Quaternion(0.6946f, 0.0407f, 0.0193f, 0.718f), ["RightHandMiddle2"] = new Quaternion(0.8665f, -0.0252f, -0.0296f, 0.4977f), ["RightHandMiddle3"] = new Quaternion(0.5541f, -0.0339f, -0.0324f, 0.8312f), ["RightHandRing1"] = new Quaternion(0.6517f, -0.0145f, -0.0277f, 0.7578f), ["RightHandRing2"] = new Quaternion(0.8166f, 0.0011f, -0.0445f, 0.5755f), ["RightHandRing3"] = new Quaternion(0.5266f, -0.0084f, -0.0224f, 0.8498f), ["RightHandPinky1"] = new Quaternion(0.6393f, -0.0446f, -0.0764f, 0.7639f), ["RightHandPinky2"] = new Quaternion(0.7087f, 0.0146f, -0.0441f, 0.704f), ["RightHandPinky3"] = new Quaternion(0.431f, 0.017f, -0.0769f, 0.8989f) }; private readonly List<KeyValuePair<Transform, Quaternion>> bones = new List<KeyValuePair<Transform, Quaternion>>(); private VisEquipment vis; private int lastHash = int.MinValue; private bool closes; private bool collected; private float recollectAt; internal static void PlayerAwakePostfix(Player __instance) { Animator val = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponentInChildren<Animator>() : null); if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent<FistHold>() == (Object)null) { ((Component)val).gameObject.AddComponent<FistHold>(); } } private void Start() { vis = ((Component)this).GetComponentInParent<VisEquipment>(); } private void OnEnable() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Application.onBeforeRender += new UnityAction(Hold); } private void OnDisable() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Application.onBeforeRender -= new UnityAction(Hold); } private void Collect() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) bones.Clear(); Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if (Fist.TryGetValue(((Object)val).name, out var value)) { bones.Add(new KeyValuePair<Transform, Quaternion>(val, value)); } } } private void Hold() { //IL_013d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)vis == (Object)null || Refs.RightItemHash == null) { return; } int num = Refs.RightItemHash.Invoke(vis); if (num != lastHash) { lastHash = num; GameObject val = ((num != 0 && (Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(num) : null); Style? s = (((Object)(object)val != (Object)null) ? Styles.OfPrefab(((Object)val).name) : ((Style?)null)); closes = s.HasValue && StyleItems.Active.Contains(s.Value) && Styles.ClosesFists(s); collected = false; recollectAt = Time.time + 0.5f; } if (!closes) { return; } if (!collected || (recollectAt > 0f && Time.time >= recollectAt)) { Collect(); collected = true; if (Time.time >= recollectAt) { recollectAt = 0f; } } foreach (KeyValuePair<Transform, Quaternion> bone in bones) { if ((Object)(object)bone.Key != (Object)null) { bone.Key.localRotation = bone.Value; } } } } internal class ComboState : MonoBehaviour { internal Style Style; internal Move Current; internal bool Running; internal string Clip; internal bool Exiting; internal float StartedAt = -10f; internal float CaptureAt; internal float LastActive = -10f; internal float EndedAt = -10f; internal float AbsentSince = -1f; internal string LastTrigger; internal float LastTriggerAt = -10f; internal Style? Preloaded; internal float NextPreload; internal static ComboState Of(Component c) { ComboState component = c.GetComponent<ComboState>(); if (!((Object)(object)component != (Object)null)) { return c.gameObject.AddComponent<ComboState>(); } return component; } internal void Begin(Style style, Move move) { Style = style; Current = move; Running = true; Clip = null; Exiting = false; StartedAt = (LastActive = Time.time); CaptureAt = Time.time + 0.05f; AbsentSince = -1f; } } internal static class HitTracking { internal static string LastOwnClip = ""; private const float NeverShowedUp = 1.5f; private const float PreloadAfter = 0.3f; private const float PreloadEvery = 0.25f; private const float EndGrace = 0.15f; internal static void SyncPostfix(ZSyncAnimation __instance) { ComboState component = ((Component)__instance).GetComponent<ComboState>(); if ((Object)(object)component != (Object)null && component.Running) { Track(__instance, component); } Preload(__instance, component); } private static void Track(ZSyncAnimation z, ComboState st) { if (st.Clip == null && Time.time > st.StartedAt + 1.5f) { End(st); } else { if (Time.time < st.CaptureAt || Refs.AnimatorOf == null) { return; } Animator val = Refs.AnimatorOf.Invoke(z); if ((Object)(object)val == (Object)null) { return; } string text = TopClip(val.GetCurrentAnimatorClipInfo(0)); string text2 = (val.IsInTransition(0) ? TopClip(val.GetNextAnimatorClipInfo(0)) : null); if (st.Clip == null) { string text3 = Styles.ClipName(st.Style, st.Current); if (text != text3 && text2 != text3) { return; } st.Clip = text3; if ((Object)(object)((Component)z).GetComponent<Player>() == (Object)(object)Player.m_localPlayer) { LastOwnClip = text3; } } if (text == st.Clip || text2 == st.Clip) { st.AbsentSince = -1f; st.LastActive = Time.time; st.Exiting = text == st.Clip && text2 != null && text2 != st.Clip; return; } if (st.AbsentSince < 0f) { st.AbsentSince = Time.time; } if (Time.time - st.AbsentSince >= 0.15f) { End(st); } } } private static void End(ComboState st) { st.Running = false; st.Exiting = false; st.EndedAt = Time.time; } private static void Preload(ZSyncAnimation z, ComboState st) { Humanoid component = ((Component)z).GetComponent<Humanoid>(); if ((Object)(object)component == (Object)null || (Object)(object)component != (Object)(object)Player.m_localPlayer || Refs.AnimatorOf == null || ((Object)(object)st != (Object)null && (st.Running || Time.time < st.LastActive + 0.3f || Time.time < st.NextPreload))) { return; } if ((Object)(object)st == (Object)null) { st = ComboState.Of((Component)(object)z); } st.NextPreload = Time.time + 0.25f; Animator val = Refs.AnimatorOf.Invoke(z); if (!((Object)(object)val == (Object)null)) { Style? style = StyleItems.StyleOf(component.GetCurrentWeapon()); if (style != st.Preloaded || (style.HasValue && !ClipSets.OursPresent(val, style.Value))) { ClipSets.Apply(val, style); st.Preloaded = style; } } } internal static void EquipPrefix(Humanoid __instance, ItemData item) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || item == null || !item.IsWeapon() || StyleItems.StyleOf(item).HasValue) { return; } ZSyncAnimation component = ((Component)__instance).GetComponent<ZSyncAnimation>(); Animator val = (((Object)(object)component != (Object)null && Refs.AnimatorOf != null) ? Refs.AnimatorOf.Invoke(component) : null); if (!((Object)(object)val == (Object)null)) { ClipSets.Apply(val, null); ComboState component2 = ((Component)component).GetComponent<ComboState>(); if ((Object)(object)component2 != (Object)null) { component2.Preloaded = null; } } } private static string TopClip(AnimatorClipInfo[] infos) { //IL_0010: 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) AnimationClip val = null; float num = -1f; for (int i = 0; i < infos.Length; i++) { AnimatorClipInfo val2 = infos[i]; if ((Object)(object)((AnimatorClipInfo)(ref val2)).clip != (Object)null && ((AnimatorClipInfo)(ref val2)).weight > num) { val = ((AnimatorClipInfo)(ref val2)).clip; num = ((AnimatorClipInfo)(ref val2)).weight; } } if (!((Object)(object)val != (Object)null)) { return null; } return ((Object)val).name; } } internal static class MultiHit { private sealed class Hits { public Style Style; public Move Move; public int Next; } private static readonly ConditionalWeakTable<Attack, Hits> running = new ConditionalWeakTable<Attack, Hits>(); internal static void Start(Attack started, Style style, Move move) { running.Remove(started); running.Add(started, new Hits { Style = style, Move = move }); } internal static void OnAttackTriggerPrefix(Attack __instance) { if (__instance != null && running.TryGetValue(__instance, out var value)) { __instance.m_damageMultiplier = Styles.HitDamage(value.Style, value.Move, value.Next++); } } } [BepInPlugin("andythedemon.combobrawler", "Combo Brawler", "1.0.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string Guid = "andythedemon.combobrawler"; public const string PluginName = "Combo Brawler"; public const string Version = "1.0.2"; internal const string ComboSpearGuid = "andythedemon.combospear"; internal static ConfigEntry<bool> Enabled; internal static ManualLogSource Log; internal static bool ComboSpearLoaded; internal static string PluginFolder; private static Harmony harmony; private void Awake() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Turns Combo Brawler on or off. Off: fist weapons attack, block and parry exactly as in vanilla. Takes effect the next time the game starts."); if (!Enabled.Value) { Log.LogInfo((object)"Combo Brawler 1.0.2 is turned off in its config (General / Enabled) - nothing is changed."); return; } ComboSpearLoaded = Chainloader.PluginInfos.ContainsKey("andythedemon.combospear"); PluginFolder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); harmony = new Harmony("andythedemon.combobrawler"); Refs.Init(); Patch("the fist weapon styles", delegate { harmony.Patch((MethodBase)AccessTools.Method(typeof(ObjectDB), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, HM(typeof(StyleItems), "ObjectDBPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(ObjectDB), "CopyOtherDB", (Type[])null, (Type[])null), (HarmonyMethod)null, HM(typeof(StyleItems), "ObjectDBPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); }); Patch("the combo triggers", delegate { harmony.Patch((MethodBase)AccessTools.Method(typeof(ZSyncAnimation), "RPC_SetTrigger", (Type[])null, (Type[])null), HM(typeof(Triggers), "Prefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); }); Patch("the move tracking", delegate { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown harmony.Patch((MethodBase)AccessTools.Method(typeof(ZSyncAnimation), "SyncParameters", (Type[])null, (Type[])null), (HarmonyMethod)null, HM(typeof(HitTracking), "SyncPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Humanoid), "EquipItem", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.Method(typeof(HitTracking), "EquipPrefix", (Type[])null, (Type[])null)) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); }); Patch("the specials", delegate { harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "HaveQueuedChain", (Type[])null, (Type[])null), (HarmonyMethod)null, HM(typeof(Specials), "HaveQueuedChainPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Humanoid), "StartAttack", new Type[2] { typeof(Character), typeof(bool) }, (Type[])null), HM(typeof(Specials), "StartAttackPrefix"), HM(typeof(Specials), "StartAttackPostfix"), (HarmonyMethod)null, HM(typeof(Specials), "StartAttackFinalizer"), (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(Attack), "OnAttackTrigger", (Type[])null, (Type[])null), HM(typeof(MultiHit), "OnAttackTriggerPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); }); Patch("the wolf's movement", delegate { harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, HM(typeof(WolfMotion), "PlayerAwakePostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); }); Patch("closed fists in the gloves", delegate { harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "Awake", (Type[])null, (Type[])null), (HarmonyMethod)null, HM(typeof(FistHold), "PlayerAwakePostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); }); if (ComboSpearLoaded) { Log.LogInfo((object)"True damage numbers: left to Combo Spear."); } else { Patch("the true damage numbers", delegate { TrueDamage.Register(harmony); }); } Log.LogInfo((object)"Combo Brawler 1.0.2 loaded."); } internal static void Patch(string feature, Action register) { try { register(); } catch (Exception ex) { Log.LogError((object)("Could not patch " + feature + " (" + ex.GetType().Name + ": " + ex.Message + "); it is off.")); } } internal static HarmonyMethod HM(Type type, string method) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown return new HarmonyMethod(AccessTools.Method(type, method, (Type[])null, (Type[])null)); } } internal static class Refs { internal static FieldRef<Humanoid, Attack> CurrentAttack; internal static FieldRef<ZSyncAnimation, Animator> AnimatorOf; internal static FieldRef<Player, float> QueuedAttack; internal static FieldRef<Player, float> QueuedSecond; internal static FieldRef<Player, bool> AttackHold; internal static FieldRef<Player, bool> SecondaryHold; internal static FieldRef<Attack, int> ChainLevel; internal static FieldRef<Character, CharacterAnimEvent> AnimEvent; internal static FieldRef<Player, Quaternion> LookYaw; internal static FieldRef<VisEquipment, int> RightItemHash; internal static FieldRef<VisEquipment, GameObject> RightItemInstance; internal static FieldRef<VisEquipment, GameObject> LeftItemInstance; internal static void Init() { CurrentAttack = Get<Humanoid, Attack>("m_currentAttack"); AnimatorOf = Get<ZSyncAnimation, Animator>("m_animator"); QueuedAttack = Get<Player, float>("m_queuedAttackTimer"); QueuedSecond = Get<Player, float>("m_queuedSecondAttackTimer"); AttackHold = Get<Player, bool>("m_attackHold"); SecondaryHold = Get<Player, bool>("m_secondaryAttackHold"); ChainLevel = Get<Attack, int>("m_currentAttackCainLevel"); AnimEvent = Get<Character, CharacterAnimEvent>("m_animEvent"); LookYaw = Get<Player, Quaternion>("m_lookYaw"); RightItemHash = Get<VisEquipment, int>("m_currentRightItemHash"); RightItemInstance = Get<VisEquipment, GameObject>("m_rightItemInstance"); LeftItemInstance = Get<VisEquipment, GameObject>("m_leftItemInstance"); } internal static bool ChainPointReached(Character c) { CharacterAnimEvent val = ((AnimEvent != null) ? AnimEvent.Invoke(c) : null); if ((Object)(object)val != (Object)null) { return val.CanChain(); } return false; } private static FieldRef<T, F> Get<T, F>(string field) where T : class { try { return AccessTools.FieldRefAccess<T, F>(field); } catch (Exception ex) { Plugin.Log.LogError((object)("Field " + typeof(T).Name + "." + field + " not found (" + ex.GetType().Name + "); the feature that needs it is off.")); return null; } } } internal static class Specials { internal const float ChainWindow = 0.25f; internal static void HaveQueuedChainPostfix(Player __instance, ref bool __result) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && Refs.CurrentAttack != null) { ComboState component = ((Component)__instance).GetComponent<ComboState>(); if (!((Object)(object)component == (Object)null) && component.Running && StyleItems.StyleOf(((Humanoid)__instance).GetCurrentWeapon()).HasValue && Refs.CurrentAttack.Invoke((Humanoid)(object)__instance) != null && Refs.QueuedSecond != null && Refs.QueuedSecond.Invoke(__instance) > 0f) { __result = Refs.ChainPointReached((Character)(object)__instance) && ComboGraph.ChainsAtChainPoint(component.Current, Press.Special); } } } internal static bool StartAttackPrefix(Humanoid __instance, bool secondaryAttack, out string __state) { __state = null; if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } ItemData currentWeapon = __instance.GetCurrentWeapon(); Style? style = StyleItems.StyleOf(currentWeapon); if (!style.HasValue) { return true; } ComboState component = ((Component)__instance).GetComponent<ComboState>(); if (!secondaryAttack) { Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val != null) { return !SpecialPending(val); } return true; } if ((Object)(object)component != (Object)null && component.Running && component.StartedAt >= Time.time) { return false; } Attack val2 = currentWeapon.m_shared?.m_secondaryAttack; if (val2 == null) { return true; } Move current = (((Object)(object)component != (Object)null) ? component.Current : Move.None); bool inWindow = (Object)(object)component != (Object)null && (component.Running || Time.time - component.EndedAt <= 0.25f); Move m = ComboGraph.Next(current, Press.Special, inWindow); __state = val2.m_attackAnimation; val2.m_attackAnimation = Styles.SpecialTrigger(style.Value, m); return true; } private static bool SpecialPending(Player p) { if (Refs.QueuedSecond == null || !(Refs.QueuedSecond.Invoke(p) > 0f)) { if (Refs.SecondaryHold != null) { return Refs.SecondaryHold.Invoke(p); } return false; } return true; } internal static void StartAttackFinalizer(Humanoid __instance, bool secondaryAttack, string __state) { if (__state != null) { Attack val = __instance.GetCurrentWeapon()?.m_shared?.m_secondaryAttack; if (val != null) { val.m_attackAnimation = __state; } } } internal static void StartAttackPostfix(Humanoid __instance, bool secondaryAttack, bool __result) { if (!__result || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || Refs.CurrentAttack == null) { return; } Attack val = Refs.CurrentAttack.Invoke(__instance); Style? style = StyleItems.StyleOf(__instance.GetCurrentWeapon()); if (val == null || !style.HasValue) { return; } Move move = MoveOf(val, style.Value, secondaryAttack); if (move != Move.None) { val.m_damageMultiplier = Styles.HitDamage(style.Value, move, 0); val.m_staggerMultiplier = Styles.Stagger(style.Value, move); val.m_lastChainDamageMultiplier = 1f; MultiHit.Start(val, style.Value, move); float num = Styles.Stamina(style.Value, move); if (num > 0f) { val.m_attackStamina = num; } } } private static Move MoveOf(Attack a, Style style, bool secondary) { if (secondary) { if (!Styles.ParseTrigger(a.m_attackAnimation, out var style2, out var move) || style2 != style) { return Move.None; } return move; } if (a.m_attackAnimation != Styles.AttackName(style)) { return Move.None; } int num = ((Refs.ChainLevel != null) ? Refs.ChainLevel.Invoke(a) : 0); return (Move)(1 + Mathf.Clamp(num, 0, 2)); } } internal static class StyleItems { internal static readonly HashSet<Style> Active = new HashSet<Style> { Style.Bear, Style.Wolf, Style.Brawler }; private static readonly Dictionary<SharedData, Style> styled = new Dictionary<SharedData, Style>(); internal static void ObjectDBPostfix(ObjectDB __instance) { Register(__instance); } internal static void Register(ObjectDB db) { if ((Object)(object)db == (Object)null || db.m_items == null) { return; } Dictionary<Style, int> dictionary = new Dictionary<Style, int>(); foreach (GameObject item in db.m_items) { if (!((Object)(object)item == (Object)null)) { SharedData val = item.GetComponent<ItemDrop>()?.m_itemData?.m_shared; if (Apply(((Object)item).name, val)) { dictionary.TryGetValue(styled[val], out var value); dictionary[styled[val]] = value + 1; } } } foreach (KeyValuePair<Style, int> item2 in dictionary) { Plugin.Log.LogInfo((object)$"{item2.Key} style on {item2.Value} items."); } } internal static Style? StyleOf(ItemData item) { SharedData val = item?.m_shared; if (val == null) { return null; } if (styled.TryGetValue(val, out var value)) { return value; } if (!((Object)(object)item.m_dropPrefab != (Object)null) || !Apply(((Object)item.m_dropPrefab).name, val)) { return null; } return styled[val]; } private static bool Apply(string prefab, SharedData s) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (s == null || s.m_attack == null) { return false; } Style? style = Styles.OfPrefab(prefab); if (!style.HasValue || !Active.Contains(style.Value)) { return false; } if (styled.ContainsKey(s)) { return true; } Attack attack = s.m_attack; attack.m_attackAnimation = Styles.AttackName(style.Value); attack.m_attackChainLevels = 3; attack.m_resetChainIfHit = (DestructibleType)0; styled[s] = style.Value; return true; } } public enum Style { Bear, Brawler, Wolf } public static class Styles { public static readonly string[] Prefabs = new string[6] { "FistBjornClaw", "FistBjornUndeadClaw", "FistFenrirClaw", "FistGold", "FistGold_BloodLightning", "FistGold_FrostFire" }; private static readonly string[,] Hosts = new string[9, 2] { { "greatsword0", "Greatsword BaseAttack (1)" }, { "greatsword1", "Greatsword BaseAttack (2)" }, { "greatsword2", "Greatsword BaseAttack (3)" }, { "axe_secondary", "Axe Secondary Attack" }, { "mace_secondary", "MaceAltAttack" }, { "dualaxes_secondary", "DualAxes Attack Cleave" }, { "battleaxe_attack0", "BattleAxe1" }, { "battleaxe_attack1", "BattleAxe2" }, { "battleaxe_attack2", "BattleAxe_Combo3" } }; private static readonly float[] BrawlerDamage = new float[9] { 0.675f, 0.7f, 0.75f, 0.75f, 0.75f, 0.775f, 0.75f, 0.75f, 0.8f }; public const float LastChainBonus = 1f; public static Style? OfPrefab(string prefabName) { switch (prefabName) { case "FistBjornClaw": case "FistBjornUndeadClaw": return Style.Bear; case "FistFenrirClaw": return Style.Wolf; case "FistGold": case "FistGold_BloodLightning": case "FistGold_FrostFire": return Style.Brawler; default: return null; } } public static string AttackName(Style s) { return "brawl_" + s.ToString().ToLowerInvariant(); } public static string SpecialTrigger(Style s, Move m) { switch (m) { case Move.S1: case Move.S2: case Move.S3: return AttackName(s) + "_s" + (int)(m - 4 + 1); case Move.H1: case Move.H2: case Move.H3: return AttackName(s) + "_h" + (int)(m - 7 + 1); default: return null; } } public static bool ParseTrigger(string trigger, out Style style, out Move move) { style = Style.Bear; move = Move.None; if (trigger == null || !trigger.StartsWith("brawl_", StringComparison.Ordinal)) { return false; } Style[] array = (Style[])Enum.GetValues(typeof(Style)); int num = 0; while (num < array.Length) { Style style2 = array[num]; string text = AttackName(style2); string text2; if (trigger.StartsWith(text, StringComparison.Ordinal)) { text2 = trigger.Substring(text.Length); if (text2 == null) { goto IL_014c; } int length = text2.Length; if (length != 1) { if (length != 3) { goto IL_014c; } switch (text2[2]) { case '1': break; case '2': goto IL_00e2; case '3': goto IL_0100; default: goto IL_014c; } if (!(text2 == "_s1")) { if (!(text2 == "_h1")) { goto IL_014c; } move = Move.H1; } else { move = Move.S1; } } else { switch (text2[0]) { case '0': break; case '1': goto IL_0123; case '2': goto IL_0128; default: goto IL_014c; } move = Move.L1; } goto IL_014e; } num++; continue; IL_014c: return false; IL_0123: move = Move.L2; goto IL_014e; IL_00e2: if (!(text2 == "_s2")) { if (!(text2 == "_h2")) { goto IL_014c; } move = Move.H2; } else { move = Move.S2; } goto IL_014e; IL_0128: move = Move.L3; goto IL_014e; IL_014e: style = style2; return true; IL_0100: if (!(text2 == "_s3")) { if (!(text2 == "_h3")) { goto IL_014c; } move = Move.H3; } else { move = Move.S3; } goto IL_014e; } return false; } public static string ClipName(Style s, Move m) { return ClipStyle(s, m).ToString() + m; } public static Style ClipStyle(Style s, Move m) { return s; } public static string HostTrigger(Move m) { if (m != Move.None) { return Hosts[(int)(m - 1), 0]; } return null; } public static string HostClip(Move m) { if (m != Move.None) { return Hosts[(int)(m - 1), 1]; } return null; } public static float Damage(Style s, Move m) { switch (s) { case Style.Brawler: return BrawlerDamage[(int)(m - 1)]; case Style.Wolf: if (m > Move.L3) { if (m < Move.H1) { return 1.8f; } return 1.5f; } return 1.2f; default: if (m >= Move.L1 && m <= Move.L3) { return 2f; } if (m >= Move.H1) { return 2.5f; } return 3f; } } public static bool ClosesFists(Style? s) { return s.HasValue; } public static float Stagger(Style s, Move m) { if (ClipStyle(s, m) != Style.Bear || m != Move.H3) { return 1f; } return 3f; } public static float[] HitShares(Style s, Move m) { if (s == Style.Wolf && (m == Move.S1 || m == Move.H2 || m == Move.S2)) { return new float[2] { 0.5f, 0.5f }; } return new float[1] { 1f }; } public static float HitDamage(Style s, Move m, int hit) { float[] array = HitShares(s, m); if (array.Length == 0) { return 0f; } return Damage(s, m) * array[Math.Min(Math.Max(hit, 0), array.Length - 1)]; } public static float Stamina(Style s, Move m) { if (s == Style.Wolf) { switch (m) { case Move.S1: case Move.S2: case Move.S3: return 18f; case Move.H1: case Move.H2: case Move.H3: return 22f; default: return 0f; } } switch (m) { case Move.S1: case Move.S2: case Move.S3: return 20f; case Move.H1: case Move.H2: case Move.H3: return 25f; default: return 0f; } } } internal static class Triggers { internal const string Ignored = "brawl_dup_ignored"; internal static void Prefix(ZSyncAnimation __instance, ref string name) { if (name == null || name.StartsWith("brawl_dup_ignored", StringComparison.Ordinal) || !Styles.ParseTrigger(name, out var style, out var move)) { return; } ComboState comboState = ComboState.Of((Component)(object)__instance); bool flag = comboState.Running && comboState.Current == move && Time.time < comboState.LastActive + 0.05f; if (name == comboState.LastTrigger && (flag || Time.time - comboState.LastTriggerAt < 0.12f)) { Plugin.Log.LogDebug((object)("Duplicate trigger '" + name + "' swallowed (would have restarted the move).")); name = "brawl_dup_ignored"; return; } comboState.LastTrigger = name; comboState.LastTriggerAt = Time.time; comboState.Begin(style, move); Animator val = ((Refs.AnimatorOf != null) ? Refs.AnimatorOf.Invoke(__instance) : null); if ((Object)(object)val != (Object)null) { ClipSets.Apply(val, style); } name = Styles.HostTrigger(move); } } internal static class TrueDamage { [ThreadStatic] private static HitData current; internal static void Register(Harmony harmony) { MethodInfo methodInfo = AccessTools.Method(typeof(Character), "ApplyDamage", new Type[4] { typeof(HitData), typeof(bool), typeof(bool), typeof(DamageModifier) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(DamageText), "ShowText", new Type[4] { typeof(DamageModifier), typeof(Vector3), typeof(float), typeof(bool) }, (Type[])null); if (methodInfo == null || methodInfo2 == null) { Plugin.Log.LogError((object)"Character.ApplyDamage / DamageText.ShowText not found; damage numbers are left as they are."); return; } harmony.Patch((MethodBase)methodInfo, Plugin.HM(typeof(TrueDamage), "ApplyPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, Plugin.HM(typeof(TrueDamage), "ApplyFinalizer"), (HarmonyMethod)null); harmony.Patch((MethodBase)methodInfo2, Plugin.HM(typeof(TrueDamage), "ShowTextPrefix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.Log.LogInfo((object)"True damage numbers: on (shows the damage a hit really deals)."); } internal static void ApplyPrefix(HitData hit, out HitData __state) { __state = current; current = hit; } internal static void ApplyFinalizer(HitData __state) { current = __state; } internal static void ShowTextPrefix(ref float dmg) { if (current != null) { dmg = current.GetTotalDamage(); } } } public static class WolfMath { public const float PassableRadius = 1.2f; public static float AirTime(float height, float gravity) { if (height <= 0f || gravity <= 0f) { return 0f; } return 2f * (float)Math.Sqrt(2f * height / gravity); } public static (float vForward, float vSide, float vUp) Launch(float forward, float side, float height, float gravity) { float num = Math.Max(0.1f, gravity); float item = ((height > 0f) ? ((float)Math.Sqrt(2f * num * height)) : 0f); float num2 = AirTime(height, num); if (!(num2 > 0.01f)) { return (vForward: 0f, vSide: 0f, vUp: item); } return (vForward: forward / num2, vSide: side / num2, vUp: item); } public static float DashDistance(float targetDistance, float targetRadius, bool hasTarget) { if (!hasTarget) { return 2.8f; } if (targetRadius > 1.2f) { return Math.Max(0f, targetDistance - targetRadius - 0.8f); } return Math.Min(4.5f, targetDistance + targetRadius + 1f); } public static bool ShouldLaunch(bool isOwner, bool onGround) { return isOwner && onGround; } public static bool TurnsAfterDash(bool hasTarget, float targetRadius) { if (hasTarget) { return targetRadius <= 1.2f; } return false; } public static float ReturnDistance(float targetDistance, float targetRadius, float max) { return Math.Max(0f, Math.Min(max, targetDistance - targetRadius - 0.5f)); } public static float GlowAlpha(float elapsed, float duration, float peak) { if (duration <= 0f || elapsed <= 0f || elapsed >= duration) { return 0f; } float num = elapsed / duration; float num2 = Math.Min(1f, num / 0.15f); float num3 = Math.Max(0f, (num - 0.6f) / 0.4f); return peak * num2 * num2 * (3f - 2f * num2) * (1f - num3 * num3 * (3f - 2f * num3)); } public static float PivotFraction(float elapsed, float duration) { if (duration <= 0f) { return 1f; } float num = Math.Max(0f, Math.Min(1f, elapsed / duration)); return num * num * (3f - 2f * num); } } internal class WolfMotion : MonoBehaviour { private Character owner; private Character dashTarget; private Character turnTarget; private Character Owner { get { if (!((Object)(object)owner != (Object)null)) { return owner = ((Component)this).GetComponentInParent<Character>(); } return owner; } } private static float Gravity => Mathf.Max(0.1f, 0f - Physics.gravity.y); internal static void PlayerAwakePostfix(Player __instance) { Animator val = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponentInChildren<Animator>() : null); if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent<WolfMotion>() == (Object)null) { ((Component)val).gameObject.AddComponent<WolfMotion>(); } } public void BrawlLeap(string args) { if (CanLaunch(out var c) && Parse(args, 3, out var a)) { Launch(c, a[0], a[1], a[2]); } } public void BrawlDash(string args) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) if (CanLaunch(out var c) && Parse(args, 2, out var a)) { dashTarget = FindTarget(c, 3.5f, 50f); bool flag = (Object)(object)dashTarget != (Object)null; float targetRadius = (flag ? dashTarget.GetRadius() : 0f); float targetDistance; if (!flag) { targetDistance = 0f; } else { Vector3 val = Flat(((Component)dashTarget).transform.position - ((Component)c).transform.position); targetDistance = ((Vector3)(ref val)).magnitude; } float num = WolfMath.DashDistance(targetDistance, targetRadius, flag); if (flag && WolfMath.TurnsAfterDash(hasTarget: true, targetRadius)) { ((MonoBehaviour)this).StartCoroutine(IgnoreCollisions(c, dashTarget, WolfMath.AirTime(a[1], Gravity) + 0.3f)); } float result = 0f; string[] array = args.Split(','); if (array.Length > 2) { float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out result); } Launch(c, Mathf.Min(num, a[0]), result, a[1]); } } public void BrawlTurn(string args) { Character val = Owner; Character val2 = dashTarget; dashTarget = null; turnTarget = null; if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || val2.IsDead() || !WolfMath.TurnsAfterDash(hasTarget: true, val2.GetRadius())) { return; } ZNetView component = ((Component)val).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid() && component.IsOwner()) { turnTarget = val2; float result = 0f; if (!string.IsNullOrEmpty(args)) { float.TryParse(args, NumberStyles.Float, CultureInfo.InvariantCulture, out result); } ((MonoBehaviour)this).StartCoroutine(Pivot(val, val2, result)); } } public void BrawlReturn(string args) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) Character val = turnTarget; turnTarget = null; if (!((Object)(object)val == (Object)null) && !val.IsDead() && CanLaunch(out var c) && Parse(args, 2, out var a)) { Vector3 val2 = Flat(((Component)val).transform.position - ((Component)c).transform.position); float num = WolfMath.ReturnDistance(((Vector3)(ref val2)).magnitude, val.GetRadius(), a[0]); if (num > 0.05f) { Launch(c, num, 0f, a[1]); } } } public void BrawlClawGlow(string args) { Character val = Owner; if (!((Object)(object)val == (Object)null) && !val.IsDead()) { float result = 1f; if (!string.IsNullOrEmpty(args)) { float.TryParse(args, NumberStyles.Float, CultureInfo.InvariantCulture, out result); } ((MonoBehaviour)this).StartCoroutine(ClawGlow.Run(val, result)); } } private static IEnumerator Pivot(Character c, Character t, float seconds) { Quaternion from = ((Component)c).transform.rotation; float el = 0f; while (!((Object)(object)c == (Object)null) && !((Object)(object)t == (Object)null) && !c.IsDead() && !t.IsDead()) { Vector3 val = Flat(((Component)t).transform.position - ((Component)c).transform.position); if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { break; } Quaternion val2 = Quaternion.Slerp(from, Quaternion.LookRotation(((Vector3)(ref val)).normalized), WolfMath.PivotFraction(el, seconds)); ((Component)c).transform.rotation = val2; c.SetLookDir(val2 * Vector3.forward, 0f); Player val3 = (Player)(object)((c is Player) ? c : null); if (val3 != null && Refs.LookYaw != null) { Refs.LookYaw.Invoke(val3) = val2; } if (el >= seconds) { break; } yield return null; el += Time.deltaTime; } } private bool CanLaunch(out Character c) { c = Owner; if ((Object)(object)c == (Object)null || c.IsDead()) { return false; } ZNetView component = ((Component)c).GetComponent<ZNetView>(); return WolfMath.ShouldLaunch((Object)(object)component != (Object)null && component.IsValid() && component.IsOwner(), c.IsOnGround()); } private static void Launch(Character c, float forward, float side, float height) { //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_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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) //IL_001a: 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) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Flat(((Component)c).transform.forward); Vector3 normalized = ((Vector3)(ref val)).normalized; Vector3 val2 = Vector3.Cross(Vector3.up, normalized); var (num, num2, num3) = WolfMath.Launch(forward, side, height, Gravity); c.ForceJump(normalized * num + val2 * num2 + Vector3.up * num3, false); } private static Character FindTarget(Character c, float range, float halfAngle) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0071: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) Character result = null; float num = float.MaxValue; Vector3 val = Flat(((Component)c).transform.forward); Vector3 normalized = ((Vector3)(ref val)).normalized; foreach (Character allCharacter in Character.GetAllCharacters()) { if (!((Object)(object)allCharacter == (Object)null) && !((Object)(object)allCharacter == (Object)(object)c) && !allCharacter.IsDead() && !allCharacter.IsPlayer() && !allCharacter.IsTamed()) { Vector3 val2 = Flat(((Component)allCharacter).transform.position - ((Component)c).transform.position); float magnitude = ((Vector3)(ref val2)).magnitude; if (!(magnitude > range + allCharacter.GetRadius()) && !(magnitude < 0.01f) && !(Vector3.Angle(normalized, val2) > halfAngle) && magnitude < num) { num = magnitude; result = allCharacter; } } } return result; } private static IEnumerator IgnoreCollisions(Character c, Character t, float seconds) { Collider[] mine = ((Component)c).GetComponentsInChildren<Collider>(); Collider[] theirs = ((Component)t).GetComponentsInChildren<Collider>(); SetIgnore(mine, theirs, ignore: true); yield return (object)new WaitForSeconds(seconds); SetIgnore(mine, theirs, ignore: false); } private static void SetIgnore(Collider[] a, Collider[] b, bool ignore) { foreach (Collider val in a) { foreach (Collider val2 in b) { if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null) { Physics.IgnoreCollision(val, val2, ignore); } } } } private static Vector3 Flat(Vector3 v) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) v.y = 0f; return v; } private static bool Parse(string args, int n, out float[] a) { a = new float[n]; string[] array = (args ?? "").Split(','); if (array.Length < n) { return false; } for (int i = 0; i < n; i++) { if (!float.TryParse(array[i], NumberStyles.Float, CultureInfo.InvariantCulture, out a[i])) { return false; } } return true; } } }