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 All Allies Emote v1.0.0
AllAlliesEmote.dll
Decompiled 7 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EmotesAPI; using HarmonyLib; using Microsoft.CodeAnalysis; using R2API.Networking; using R2API.Networking.Interfaces; using RiskOfOptions; using RiskOfOptions.Options; using RoR2; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.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 AllAlliesEmote { [BepInPlugin("com.chaz.allalliesemote", "All Allies Emote", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class AllAlliesEmotePlugin : BaseUnityPlugin { [CompilerGenerated] private static class <>O { public static Action<CharacterBody> <0>__OnBodyStart; public static AnimationChanged <1>__OnAnimChanged; } public const string GUID = "com.chaz.allalliesemote"; public const string Name = "All Allies Emote"; public const string Version = "1.0.0"; private const string EmotesGUID = "com.weliveinasociety.CustomEmotesAPI"; internal static ManualLogSource Log; internal static ConfigEntry<bool> alliesEmote; internal static ConfigEntry<bool> fallbackDance; internal static ConfigEntry<bool> allyAudio; private void Awake() { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; alliesEmote = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Allies emote with you", true, "When you emote, all of your allies (drones, turrets, item pets...) emote with you. Teammates and their allies are never affected."); fallbackDance = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Dance for allies without emotes", true, "Allies that can't be given an emote skeleton (rare: ones without a skinned model) bob and sway to the beat instead."); allyAudio = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Ally emote sounds", false, "Let each ally play its own copy of an emote's sound (for emotes whose sound isn't shared). Off, only you are heard."); if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions")) { ModSettings.Register(); } new Harmony("com.chaz.allalliesemote").PatchAll(typeof(AllyAudio)); RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, (Action)delegate { try { AllyRigs.RelinkAll(); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Emote skeleton repair failed: " + ex)); } }); CharacterBody.onBodyStartGlobal += Allies.OnBodyStart; object obj = <>O.<1>__OnAnimChanged; if (obj == null) { AnimationChanged val = Allies.OnAnimChanged; <>O.<1>__OnAnimChanged = val; obj = (object)val; } CustomEmotesAPI.animChanged += (AnimationChanged)obj; } private void Update() { if (Object.op_Implicit((Object)(object)Run.instance)) { Allies.Tick(); } } private void LateUpdate() { if (Object.op_Implicit((Object)(object)Run.instance)) { Allies.KeepInStep(); } } } internal static class AllyAudio { [HarmonyPatch(typeof(AkSoundEngine), "PostEvent", new Type[] { typeof(string), typeof(GameObject) })] [HarmonyPrefix] private static bool PostEvent(GameObject __1, ref uint __result) { if (Object.op_Implicit((Object)(object)__1) && !AllAlliesEmotePlugin.allyAudio.Value && Allies.silenced.Contains(__1)) { __result = 0u; return false; } return true; } } internal static class Allies { private struct Ally { public CharacterBody body; public CharacterMaster owner; public BoneMapper mapper; } private const float ScanInterval = 0.25f; private const string TurretTauntGUID = "com.kanggamming.EngineerTurretTaunt"; internal static readonly HashSet<GameObject> silenced = new HashSet<GameObject>(); private static readonly List<Ally> allies = new List<Ally>(); private static readonly Dictionary<CharacterBody, BoneMapper> mappers = new Dictionary<CharacterBody, BoneMapper>(); private static readonly Dictionary<CharacterBody, (string clip, int start)> sent = new Dictionary<CharacterBody, (string, int)>(); private static readonly Dictionary<CharacterMaster, (int start, float at)> ownerStarts = new Dictionary<CharacterMaster, (int, float)>(); private static readonly Dictionary<BoneMapper, int> justStarted = new Dictionary<BoneMapper, int>(); private static float nextScan; private static float MirrorDelay { get { if (!Chainloader.PluginInfos.ContainsKey("com.kanggamming.EngineerTurretTaunt")) { return 0f; } return 0.2f; } } public static CharacterMaster OwnerOf(CharacterBody body) { CharacterMaster val = (Object.op_Implicit((Object)(object)body) ? body.master : null); if (!Object.op_Implicit((Object)(object)val) || Object.op_Implicit((Object)(object)val.playerCharacterMasterController)) { return null; } for (int i = 0; i < 8; i++) { CharacterMaster val2 = (Object.op_Implicit((Object)(object)val.minionOwnership) ? val.minionOwnership.ownerMaster : null); if (!Object.op_Implicit((Object)(object)val2)) { return null; } if (Object.op_Implicit((Object)(object)val2.playerCharacterMasterController)) { return val2; } val = val2; } return null; } public static string ClipOf(CharacterMaster player) { return ClipOf(MapperOf(Object.op_Implicit((Object)(object)player) ? player.GetBody() : null)); } private static string ClipOf(BoneMapper mapper) { if (!Object.op_Implicit((Object)(object)mapper) || mapper.currentClip == null || string.IsNullOrEmpty(mapper.currentClipName)) { return "none"; } return mapper.currentClipName; } private static BoneMapper MapperOf(CharacterBody body) { if (!Object.op_Implicit((Object)(object)body)) { return null; } if (mappers.TryGetValue(body, out var value) && Object.op_Implicit((Object)(object)value)) { return value; } Transform val = (Object.op_Implicit((Object)(object)body.modelLocator) ? body.modelLocator.modelTransform : null); value = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponentInChildren<BoneMapper>(true) : null); if (Object.op_Implicit((Object)(object)value)) { mappers[body] = value; } return value; } public static void OnBodyStart(CharacterBody body) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.teamComponent) && (int)body.teamComponent.teamIndex == 1 && (!Object.op_Implicit((Object)(object)body.master) || !Object.op_Implicit((Object)(object)body.master.playerCharacterMasterController)) && !body.isPlayerControlled) { AllyRigs.ReplaceBroken(body); AllyRigs.Ensure(body); } } public static void OnAnimChanged(string newAnimation, BoneMapper mapper) { CharacterBody val = (Object.op_Implicit((Object)(object)mapper) ? mapper.mapperBody : null); if (Object.op_Implicit((Object)(object)val)) { if (Object.op_Implicit((Object)(object)val.master) && Object.op_Implicit((Object)(object)val.master.playerCharacterMasterController)) { ownerStarts.TryGetValue(val.master, out (int, float) value); ownerStarts[val.master] = (value.Item1 + 1, Time.unscaledTime); } else if (newAnimation != "none") { justStarted[mapper] = Time.frameCount; } } } public static void KeepInStep() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) foreach (Ally ally in allies) { BoneMapper mapper = ally.mapper; if (!Object.op_Implicit((Object)(object)mapper) || !Object.op_Implicit((Object)(object)mapper.a2) || !Object.op_Implicit((Object)(object)mapper.mapperBody)) { continue; } string text = ClipOf(mapper); BoneMapper val = ((text == "none") ? null : MapperOf(Object.op_Implicit((Object)(object)ally.owner) ? ally.owner.GetBody() : null)); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.a2) || ClipOf(val) != text) { continue; } AnimatorStateInfo currentAnimatorStateInfo = val.a2.GetCurrentAnimatorStateInfo(0); if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("none") || ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).length <= 0f) { continue; } mapper.a2.speed = val.a2.speed; AnimatorStateInfo currentAnimatorStateInfo2 = mapper.a2.GetCurrentAnimatorStateInfo(0); if (!justStarted.ContainsKey(mapper)) { if (((AnimatorStateInfo)(ref currentAnimatorStateInfo2)).fullPathHash != ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash) { continue; } float num = ((AnimatorStateInfo)(ref currentAnimatorStateInfo2)).normalizedTime - ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime; if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).loop) { num -= Mathf.Round(num); } if (Mathf.Abs(num) * ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).length < 0.05f) { continue; } } mapper.a2.Play(((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash, 0, ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime + Time.deltaTime * val.a2.speed / ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).length); justStarted.Remove(mapper); } if (justStarted.Count <= 0) { return; } foreach (BoneMapper item in (from kv in justStarted where !Object.op_Implicit((Object)(object)kv.Key) || Time.frameCount - kv.Value > 30 select kv.Key).ToList()) { justStarted.Remove(item); } } public static void Tick() { if (Time.unscaledTime >= nextScan) { nextScan = Time.unscaledTime + 0.25f; Scan(); } foreach (LocalUser readOnlyLocalUsers in LocalUserManager.readOnlyLocalUsersList) { if (Object.op_Implicit((Object)(object)readOnlyLocalUsers.cachedMaster)) { Mirror(readOnlyLocalUsers.cachedMaster); } } } private static void Scan() { allies.Clear(); silenced.Clear(); Forget(mappers); Forget(sent); foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList) { CharacterMaster val = OwnerOf(readOnlyInstances); if (!Object.op_Implicit((Object)(object)val)) { continue; } AllyRigs.Ensure(readOnlyInstances); BoneMapper val2 = MapperOf(readOnlyInstances); allies.Add(new Ally { body = readOnlyInstances, owner = val, mapper = val2 }); if (Object.op_Implicit((Object)(object)val2)) { silenced.Add(((Component)val2).gameObject); if (!Object.op_Implicit((Object)(object)((Component)val2).GetComponent<RigAnchor>())) { ((Component)val2).gameObject.AddComponent<RigAnchor>().mapper = val2; } } else if (AllAlliesEmotePlugin.fallbackDance.Value && Object.op_Implicit((Object)(object)readOnlyInstances.modelLocator) && Object.op_Implicit((Object)(object)readOnlyInstances.modelLocator.modelTransform)) { AllyDance allyDance = ((Component)readOnlyInstances).GetComponent<AllyDance>(); if (!Object.op_Implicit((Object)(object)allyDance)) { allyDance = ((Component)readOnlyInstances).gameObject.AddComponent<AllyDance>(); } allyDance.owner = val; } } } private static void Forget<T>(Dictionary<CharacterBody, T> map) { List<CharacterBody> list = new List<CharacterBody>(); foreach (CharacterBody key in map.Keys) { if (!Object.op_Implicit((Object)(object)key)) { list.Add(key); } } foreach (CharacterBody item in list) { map.Remove(item); } } private static void Mirror(CharacterMaster player) { BoneMapper mapper = MapperOf(player.GetBody()); string text = (AllAlliesEmotePlugin.alliesEmote.Value ? ClipOf(mapper) : "none"); ownerStarts.TryGetValue(player, out (int, float) value); foreach (Ally ally in allies) { if ((Object)(object)ally.owner != (Object)(object)player || !Object.op_Implicit((Object)(object)ally.mapper) || !Object.op_Implicit((Object)(object)ally.body) || !Object.op_Implicit((Object)(object)ally.mapper.mapperBody)) { continue; } sent.TryGetValue(ally.body, out (string, int) value2); if (value2.Item1 == text && value2.Item2 == value.Item1) { continue; } string text2 = ClipOf(ally.mapper); if (text == "none") { if (value2.Item1 != null && value2.Item1 != "none" && text2 != "none") { Send(ally.body, "none", -2); } sent[ally.body] = (text, value.Item1); } else if (!(Time.unscaledTime - value.Item2 < MirrorDelay)) { if (MirrorDelay > 0f && text2 == text && value2.Item1 == null) { sent[ally.body] = (text, value.Item1); continue; } Send(ally.body, text, Variant(mapper)); sent[ally.body] = (text, value.Item1); } } } private static int Variant(BoneMapper mapper) { CustomAnimationClip val = (Object.op_Implicit((Object)(object)mapper) ? mapper.currentClip : null); if (val == null || val.clip == null || val.clip.Length < 2) { return -2; } RuntimeAnimatorController runtimeAnimatorController = mapper.a2.runtimeAnimatorController; AnimatorOverrideController val2 = (AnimatorOverrideController)(object)((runtimeAnimatorController is AnimatorOverrideController) ? runtimeAnimatorController : null); if (val2 == null) { return -2; } List<KeyValuePair<AnimationClip, AnimationClip>> list = new List<KeyValuePair<AnimationClip, AnimationClip>>(); val2.GetOverrides(list); foreach (KeyValuePair<AnimationClip, AnimationClip> item in list) { if (!Object.op_Implicit((Object)(object)item.Value)) { continue; } for (int i = 0; i < val.clip.Length; i++) { if ((Object)(object)val.clip[i] == (Object)(object)item.Value || (val.secondaryClip != null && i < val.secondaryClip.Length && (Object)(object)val.secondaryClip[i] == (Object)(object)item.Value)) { return i; } } } return -2; } private static void Send(CharacterBody body, string clip, int variant) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown NetMessageExtensions.Send((INetMessage)new SyncAnimationToServer(((NetworkBehaviour)body).netId, clip, variant), (NetworkDestination)2); } } [DefaultExecutionOrder(10000)] internal class AllyDance : MonoBehaviour { private const float BeatsPerSecond = 2f; private const float BlendSpeed = 4f; public CharacterMaster owner; private CharacterBody body; private Transform model; private Vector3 basePosition; private Vector3 appliedPosition; private Quaternion baseRotation; private Quaternion appliedRotation; private bool applied; private float weight; private int style; private string clip; private void Awake() { body = ((Component)this).GetComponent<CharacterBody>(); } private void LateUpdate() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) Transform val = (Object.op_Implicit((Object)(object)body.modelLocator) ? body.modelLocator.modelTransform : null); if ((Object)(object)val != (Object)(object)model) { model = val; applied = false; } if (!Object.op_Implicit((Object)(object)model)) { return; } if (applied && model.localPosition == appliedPosition && model.localRotation == appliedRotation) { model.SetLocalPositionAndRotation(basePosition, baseRotation); } applied = false; string text = Allies.ClipOf(owner); bool flag = text != "none" && AllAlliesEmotePlugin.alliesEmote.Value && AllAlliesEmotePlugin.fallbackDance.Value && Object.op_Implicit((Object)(object)body.healthComponent) && body.healthComponent.alive; weight = Mathf.MoveTowards(weight, flag ? 1f : 0f, Time.deltaTime * 4f); if (!(weight <= 0f)) { if (flag && text != clip) { clip = text; style = (int)((uint)clip.GetHashCode() % 3u); } float num = Mathf.Clamp(body.bestFitRadius, 0.5f, 4f); float num2 = Time.time * 2f; float num3 = Mathf.Abs(Mathf.Sin((float)Math.PI * num2)); float num4 = Mathf.Sin((float)Math.PI * num2 * 0.5f); float num5; Quaternion val2; switch (style) { case 0: num5 = 0.15f * num3; val2 = Quaternion.Euler(0f, 25f * num4, 10f * Mathf.Sin((float)Math.PI * num2)); break; case 1: num5 = 0.1f * num3; val2 = Quaternion.Euler(0f, Time.time * 270f % 360f, 0f); break; default: num5 = 0.05f * num3; val2 = Quaternion.Euler(-20f * num3, 0f, 8f * num4); break; } basePosition = model.localPosition; baseRotation = model.localRotation; appliedPosition = basePosition + baseRotation * Vector3.up * (num5 * num * weight); appliedRotation = baseRotation * Quaternion.Slerp(Quaternion.identity, val2, weight); model.SetLocalPositionAndRotation(appliedPosition, appliedRotation); applied = true; } } private void OnDisable() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_004c: 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) if (applied && Object.op_Implicit((Object)(object)model) && model.localPosition == appliedPosition && model.localRotation == appliedRotation) { model.SetLocalPositionAndRotation(basePosition, baseRotation); } applied = false; } } internal static class AllyRigs { private const string Dancer = "RoR2/Base/Bandit2/Bandit2Body.prefab"; private static readonly Dictionary<string, string> sameModelAs = new Dictionary<string, string> { ["DTGunnerDroneBody"] = "RoR2/Base/Drones/Drone1Body.prefab", ["DTHealingDroneBody"] = "RoR2/Base/Drones/Drone2Body.prefab", ["FriendUnitBody"] = "RoR2/DLC3/DefectiveUnit/DefectiveUnitBody.prefab", ["DevotedLemurianBody"] = "RoR2/Base/Lemurian/LemurianBody.prefab", ["DevotedLemurianBruiserBody"] = "RoR2/Base/LemurianBruiser/LemurianBruiserBody.prefab" }; private static readonly MethodInfo applyAnimationStuff = AccessTools.Method("AnimationReplacements:ApplyAnimationStuff", new Type[6] { typeof(GameObject), typeof(GameObject), typeof(int), typeof(bool), typeof(bool), typeof(bool) }, (Type[])null); private static readonly List<BoneMapper> allMappers = (List<BoneMapper>)AccessTools.Field(typeof(BoneMapper), "allMappers").GetValue(null); private static readonly HashSet<CharacterBody> tried = new HashSet<CharacterBody>(); private static readonly HashSet<string> brokenRigs = new HashSet<string> { "DroneCommanderBody" }; public static bool Ensure(CharacterBody body) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.modelLocator)) ? body.modelLocator.modelTransform : null); if (!Object.op_Implicit((Object)(object)val)) { return false; } if (Object.op_Implicit((Object)(object)((Component)val).GetComponentInChildren<BoneMapper>(true))) { return true; } if (!tried.Add(body)) { return false; } tried.RemoveWhere((CharacterBody b) => !Object.op_Implicit((Object)(object)b)); try { string bodyName = BodyCatalog.GetBodyName(body.bodyIndex); if (sameModelAs.TryGetValue(bodyName ?? "", out var value) && Copy(body, val, value)) { return true; } return Generic(body, val); } catch (Exception arg) { AllAlliesEmotePlugin.Log.LogWarning((object)$"{((Object)body).name}: couldn't add an emote skeleton: {arg}"); return false; } } private static bool Copy(CharacterBody body, Transform model, string sourceKey) { //IL_013d: Unknown result type (might be due to invalid IL or missing references) BoneMapper val = DonorMapper(sourceKey); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.smr1)) { return false; } HashSet<string> rigNames = new HashSet<string>(from b in val.smr1.bones where Object.op_Implicit((Object)(object)b) select ((Object)b).name); (SkinnedMeshRenderer, int, int) tuple = (from r in ((Component)model).GetComponentsInChildren<SkinnedMeshRenderer>(true) select (r: r, matched: r.bones.Count((Transform b) => Object.op_Implicit((Object)(object)b) && rigNames.Contains(((Object)b).name)), count: r.bones.Count((Transform b) => Object.op_Implicit((Object)(object)b))) into x orderby x.matched descending select x).FirstOrDefault(); if ((Object)(object)tuple.Item1 == (Object)null || tuple.Item2 == 0 || (float)tuple.Item2 < 0.6f * (float)Mathf.Min(rigNames.Count, tuple.Item3)) { return false; } Transform val2 = CopyRig(val); BoneMapper val3 = Attach(body, model, ((Component)val2).gameObject); if (!Object.op_Implicit((Object)(object)val3)) { return false; } val3.scale = val.scale; ((Component)val3).transform.localPosition = ((Component)val).transform.localPosition; AllAlliesEmotePlugin.Log.LogInfo((object)$"{((Object)body).name}: emotes added ({((Object)((Component)val).transform.parent).name}'s skeleton, {tuple.Item2} bones)"); return true; } private static bool Generic(CharacterBody body, Transform model) { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) BoneMapper donor = DonorMapper("RoR2/Base/Bandit2/Bandit2Body.prefab"); if (!Object.op_Implicit((Object)(object)donor) || !Object.op_Implicit((Object)(object)donor.a2) || !Object.op_Implicit((Object)(object)donor.a2.avatar)) { return false; } Transform val = TopBone(model); if (!Object.op_Implicit((Object)(object)val)) { return false; } Transform val2 = CopyRig(donor); Transform[] all = ((Component)val2).GetComponentsInChildren<Transform>(true); Transform val3 = Find((HumanBodyBones)0); Transform val4 = Find((HumanBodyBones)5); if (!Object.op_Implicit((Object)(object)val3) || !Object.op_Implicit((Object)(object)val4)) { Object.Destroy((Object)(object)((Component)val2.parent).gameObject); return false; } SkinnedMeshRenderer[] componentsInChildren = ((Component)val2).GetComponentsInChildren<SkinnedMeshRenderer>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } Transform transform = new GameObject("AllyEmoteProxy").transform; transform.SetParent(model, false); Transform transform2 = new GameObject(((Object)val).name).transform; transform2.SetParent(transform, false); SkinnedMeshRenderer obj = new GameObject("AllyEmoteBones").AddComponent<SkinnedMeshRenderer>(); ((Component)obj).transform.SetParent(val2, false); obj.bones = (Transform[])(object)new Transform[1] { transform2 }; BoneMapper val5 = Attach(body, model, ((Component)val2).gameObject); if (!Object.op_Implicit((Object)(object)val5)) { Object.Destroy((Object)(object)((Component)transform).gameObject); return false; } float num = val5.a2.humanScale * Mathf.Abs(((Component)val5).transform.lossyScale.y); if (num <= 0.01f) { num = Vector3.Distance(val3.position, val4.position); } float num2 = Size(model, ((Component)val5).transform); if (num > 0.01f && num2 > 0f) { Transform transform3 = ((Component)val5).transform; transform3.localScale *= Mathf.Clamp(num2 * 0.4f, 0.3f, 2f) / num; } transform2.SetPositionAndRotation(val.position, val.rotation); val5.revertTransform = true; RigAnchor rigAnchor = ((Component)val2).gameObject.AddComponent<RigAnchor>(); rigAnchor.mapper = val5; rigAnchor.follow = val3; rigAnchor.reach = Mathf.Max(num2, 1.5f); rigAnchor.proxy = transform2; rigAnchor.bone = val; AllAlliesEmotePlugin.Log.LogInfo((object)$"{((Object)body).name}: emotes added (its {((Object)val).name} follows the dance, size {num2:0.0} m)"); return true; Transform Find(HumanBodyBones b) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) string n = HumanBone(donor, b); return ((IEnumerable<Transform>)all).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == n)); } } public static void ReplaceBroken(CharacterBody body) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) Transform val = ((Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.modelLocator)) ? body.modelLocator.modelTransform : null); if (Object.op_Implicit((Object)(object)val) && brokenRigs.Contains(BodyCatalog.GetBodyName(body.bodyIndex) ?? "")) { BoneMapper componentInChildren = ((Component)val).GetComponentInChildren<BoneMapper>(true); if (Object.op_Implicit((Object)(object)componentInChildren) && (!Object.op_Implicit((Object)(object)((Component)componentInChildren).GetComponent<RigAnchor>()) || !Object.op_Implicit((Object)(object)((Component)componentInChildren).GetComponent<RigAnchor>().follow))) { Object.DestroyImmediate((Object)(object)((Component)componentInChildren).gameObject); tried.Remove(body); Ensure(body); } } } private static Transform TopBone(Transform model) { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown //IL_00f0: Unknown result type (might be due to invalid IL or missing references) List<Transform> list = (from b in ((Component)model).GetComponentsInChildren<SkinnedMeshRenderer>(true).SelectMany((SkinnedMeshRenderer r) => r.bones) where Object.op_Implicit((Object)(object)b) && (Object)(object)b != (Object)(object)model select b).Distinct().ToList(); if (list.Count > 0) { return list.OrderBy(Depth).First(); } Transform val = null; int num = 0; foreach (Transform item in model) { Transform val2 = item; int num2 = ((Component)val2).GetComponentsInChildren<MeshRenderer>(true).Length; if (num2 > num) { num = num2; val = val2; } } if (!Object.op_Implicit((Object)(object)val)) { return null; } SkinnedMeshRenderer obj = new GameObject("AllyEmoteBones").AddComponent<SkinnedMeshRenderer>(); ((Component)obj).transform.SetParent(model, false); obj.bones = (Transform[])(object)new Transform[1] { val }; return val; } private static int Depth(Transform t) { int num = 0; Transform parent = t.parent; while (Object.op_Implicit((Object)(object)parent)) { num++; parent = parent.parent; } return num; } private static string HumanBone(BoneMapper mapper, HumanBodyBones bone) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) HumanBone val = ((IEnumerable<HumanBone>)mapper.a2.avatar.humanDescription.human).FirstOrDefault((Func<HumanBone, bool>)((HumanBone h) => ((HumanBone)(ref h)).humanName == HumanTrait.BoneName[bone])); return ((HumanBone)(ref val)).boneName; } private static float Size(Transform model, Transform rig) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) Bounds? val = null; Renderer[] componentsInChildren = ((Component)model).GetComponentsInChildren<Renderer>(); Bounds val3; foreach (Renderer val2 in componentsInChildren) { if (((Component)val2).transform.IsChildOf(rig) || val2 is ParticleSystemRenderer) { continue; } val3 = val2.bounds; if (!(((Bounds)(ref val3)).size == Vector3.zero)) { if (!val.HasValue) { val = val2.bounds; continue; } Bounds value = val.Value; ((Bounds)(ref value)).Encapsulate(val2.bounds); val = value; } } if (val.HasValue) { float[] array = new float[3]; val3 = val.Value; array[0] = ((Bounds)(ref val3)).size.x; val3 = val.Value; array[1] = ((Bounds)(ref val3)).size.y; val3 = val.Value; array[2] = ((Bounds)(ref val3)).size.z; return Mathf.Max(array); } return 0f; } private static BoneMapper DonorMapper(string key) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) GameObject val = Addressables.LoadAssetAsync<GameObject>((object)key).WaitForCompletion(); if (!Object.op_Implicit((Object)(object)val)) { return null; } return val.GetComponentInChildren<BoneMapper>(true); } private static Transform CopyRig(BoneMapper donor) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown GameObject val = new GameObject("AllAlliesEmote holder"); val.SetActive(false); GameObject obj = Object.Instantiate<GameObject>(((Component)donor).gameObject, val.transform); ((Object)obj).name = ((Object)((Component)donor).gameObject).name; Object.DestroyImmediate((Object)(object)obj.GetComponent<BoneMapper>()); return obj.transform; } private static BoneMapper Attach(CharacterBody body, Transform model, GameObject rig) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown Transform parent = rig.transform.parent; BoneMapper val; try { val = (BoneMapper)applyAnimationStuff.Invoke(null, new object[6] { ((Component)body).gameObject, rig, 0, true, false, true }); } finally { if (Object.op_Implicit((Object)(object)parent) && ((Object)parent).name == "AllAlliesEmote holder") { Object.Destroy((Object)(object)((Component)parent).gameObject); } } if (!Object.op_Implicit((Object)(object)val)) { return null; } allMappers.Remove(val); RelinkToModel(val, model); return val; } public static bool RelinkToModel(BoneMapper mapper, Transform model) { if (!Object.op_Implicit((Object)(object)mapper) || !Object.op_Implicit((Object)(object)mapper.smr1) || !Object.op_Implicit((Object)(object)mapper.smr2) || !((Component)mapper.smr2).transform.IsChildOf(((Component)mapper).transform)) { return false; } HashSet<string> rigNames = new HashSet<string>(from b in mapper.smr1.bones where Object.op_Implicit((Object)(object)b) select ((Object)b).name); SkinnedMeshRenderer val = (from r in ((Component)model).GetComponentsInChildren<SkinnedMeshRenderer>(true) where !((Component)r).transform.IsChildOf(((Component)mapper).transform) orderby r.bones.Count((Transform b) => Object.op_Implicit((Object)(object)b) && rigNames.Contains(((Object)b).name)) descending select r).FirstOrDefault(); if (!Object.op_Implicit((Object)(object)val) || !val.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && rigNames.Contains(((Object)b).name))) { return false; } mapper.smr2 = val; return true; } public static void RelinkAll() { foreach (GameObject allBodyPrefab in BodyCatalog.allBodyPrefabs) { Transform val = ((Object.op_Implicit((Object)(object)allBodyPrefab) && Object.op_Implicit((Object)(object)allBodyPrefab.GetComponent<ModelLocator>())) ? allBodyPrefab.GetComponent<ModelLocator>().modelTransform : null); BoneMapper val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponentInChildren<BoneMapper>(true) : null); if (RelinkToModel(val2, val)) { AllAlliesEmotePlugin.Log.LogInfo((object)(((Object)allBodyPrefab).name + ": emote skeleton was linked to itself, now linked to " + ((Object)val2.smr2).name)); } } } } internal static class ModSettings { public const string RiskOfOptionsGUID = "com.rune580.riskofoptions"; public static void Register() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown ModSettingsManager.SetModDescription("When you emote, all of your allies emote with you."); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(AllAlliesEmotePlugin.alliesEmote)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(AllAlliesEmotePlugin.fallbackDance)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(AllAlliesEmotePlugin.allyAudio)); } } [DefaultExecutionOrder(-10)] internal class RigAnchor : MonoBehaviour { private struct Pose { public Transform bone; public Vector3 position; public Quaternion rotation; } public BoneMapper mapper; public Transform follow; public Transform proxy; public Transform bone; public float reach = 2f; private List<Pose> rest; private List<EmoteConstraint> pins; private bool wasPinned; private string anchoredFor; private int settling; private const int SettleFrames = 3; private Vector3 offsetPosition; private Vector3 anchorPosition; private Quaternion offsetRotation; private static readonly FieldRef<EmoteConstraint, Vector3> savedPosition = AccessTools.FieldRefAccess<EmoteConstraint, Vector3>("originalPosition"); private static readonly FieldRef<EmoteConstraint, Quaternion> savedRotation = AccessTools.FieldRefAccess<EmoteConstraint, Quaternion>("originalRotation"); private void Start() { if (Object.op_Implicit((Object)(object)mapper) && Object.op_Implicit((Object)(object)mapper.a2)) { mapper.a2.cullingMode = (AnimatorCullingMode)0; if (Object.op_Implicit((Object)(object)follow)) { mapper.a2.applyRootMotion = false; } } } private void LateUpdate() { //IL_014f: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_015f: 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_0186: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)mapper) || (pins == null && !FindPins())) { return; } if (!pins.Any((EmoteConstraint c) => Object.op_Implicit((Object)(object)c) && c.constraintActive)) { if (wasPinned) { foreach (Pose item in rest) { if (Object.op_Implicit((Object)(object)item.bone)) { item.bone.SetLocalPositionAndRotation(item.position, item.rotation); } } } wasPinned = false; anchoredFor = null; Record(); return; } wasPinned = true; if (Object.op_Implicit((Object)(object)follow) && Object.op_Implicit((Object)(object)proxy) && Object.op_Implicit((Object)(object)bone)) { string currentClipName = mapper.currentClipName; if (anchoredFor != currentClipName) { anchoredFor = currentClipName; settling = 0; } Pose pose = rest.FirstOrDefault((Pose p) => (Object)(object)p.bone == (Object)(object)bone); Transform parent = bone.parent; Vector3 val = ((!Object.op_Implicit((Object)(object)pose.bone)) ? bone.position : (Object.op_Implicit((Object)(object)parent) ? parent.TransformPoint(pose.position) : pose.position)); Quaternion val2 = ((!Object.op_Implicit((Object)(object)pose.bone)) ? bone.rotation : (Object.op_Implicit((Object)(object)parent) ? (parent.rotation * pose.rotation) : pose.rotation)); if (settling < 3) { settling++; proxy.SetPositionAndRotation(val, val2); offsetRotation = Quaternion.Inverse(follow.rotation) * val2; offsetPosition = Quaternion.Inverse(follow.rotation) * (val - follow.position); anchorPosition = (Object.op_Implicit((Object)(object)parent) ? parent.InverseTransformPoint(val) : val); } else { Vector3 val3 = follow.position + follow.rotation * offsetPosition; Vector3 val4 = (Object.op_Implicit((Object)(object)bone.parent) ? bone.parent.TransformPoint(anchorPosition) : anchorPosition); proxy.SetPositionAndRotation(val4 + Vector3.ClampMagnitude(val3 - val4, reach), follow.rotation * offsetRotation); } } } private bool FindPins() { //IL_011b: 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) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) Transform parent = ((Component)mapper).transform.parent; if (!Object.op_Implicit((Object)(object)parent)) { return false; } List<EmoteConstraint> list = (from c in ((Component)parent).GetComponentsInChildren<EmoteConstraint>(true) where Object.op_Implicit((Object)(object)c.originalBone) && !c.originalBone.IsChildOf(((Component)mapper).transform) && Object.op_Implicit((Object)(object)c.emoteBone) select c).ToList(); if (list.Count == 0) { return false; } pins = list; rest = (from b in list.Select((EmoteConstraint c) => c.originalBone).Distinct() select new Pose { bone = b }).ToList(); Record(); int i; for (i = 0; i < rest.Count; i++) { EmoteConstraint val = ((IEnumerable<EmoteConstraint>)list).FirstOrDefault((Func<EmoteConstraint, bool>)((EmoteConstraint x) => (Object)(object)x.originalBone == (Object)(object)rest[i].bone && x.constraintActive)); if (Object.op_Implicit((Object)(object)val)) { rest[i] = new Pose { bone = rest[i].bone, position = savedPosition.Invoke(val), rotation = savedRotation.Invoke(val) }; } } return true; } private void Record() { //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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < rest.Count; i++) { Pose value = rest[i]; if (Object.op_Implicit((Object)(object)value.bone)) { value.position = value.bone.localPosition; value.rotation = value.bone.localRotation; rest[i] = value; } } } } }