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 RepoLimbMod v0.2.1
RepoLimbMod.dll
Decompiled 13 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("RepoLimbMod")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.2.1.0")] [assembly: AssemblyInformationalVersion("0.2.1")] [assembly: AssemblyProduct("RepoLimbMod")] [assembly: AssemblyTitle("RepoLimbMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.1.0")] [module: UnverifiableCode] [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 RepoLimbMod { internal sealed class BodyParts { internal const int Torso = 0; internal const int Count = 5; internal readonly Transform[] Roots = (Transform[])(object)new Transform[5]; internal readonly List<Renderer>[] Renderers = new List<Renderer>[5]; internal static Limb ToLimb(int index) { return index switch { 1 => Limb.LeftArm, 2 => Limb.RightArm, 3 => Limb.LeftLeg, 4 => Limb.RightLeg, _ => Limb.None, }; } internal static int ToIndex(Limb limb) { return limb switch { Limb.LeftArm => 1, Limb.RightArm => 2, Limb.LeftLeg => 3, Limb.RightLeg => 4, _ => 0, }; } internal static BodyParts Collect(PlayerAvatarVisuals visuals) { BodyParts bodyParts = new BodyParts(); Transform[] componentsInChildren = ((Component)visuals).GetComponentsInChildren<Transform>(true); Transform val = (((Object)(object)visuals.playerAvatarRightArm != (Object)null) ? visuals.playerAvatarRightArm.rightArmTransform : null); Transform val2 = Find(componentsInChildren, "ANIM HEAD BOT"); bodyParts.Roots[0] = Find(componentsInChildren, "ANIM BODY BOT"); bodyParts.Roots[1] = Find(componentsInChildren, "ANIM ARM L"); bodyParts.Roots[2] = (((Object)(object)val != (Object)null) ? val : Find(componentsInChildren, "ANIM ARM R")); bodyParts.Roots[3] = Find(componentsInChildren, "ANIM LEG L BOT") ?? Find(componentsInChildren, "ANIM LEG L TOP"); bodyParts.Roots[4] = Find(componentsInChildren, "ANIM LEG R BOT") ?? Find(componentsInChildren, "ANIM LEG R TOP"); Transform val3 = (((Object)(object)visuals.playerAvatarRightArm != (Object)null) ? visuals.playerAvatarRightArm.grabberTransform : null); for (int i = 0; i < 5; i++) { List<Renderer> list = new List<Renderer>(); Transform val4 = bodyParts.Roots[i]; if ((Object)(object)val4 == (Object)null) { Plugin.Log.LogWarning((object)$"Hittade ingen transform för kroppsdel {i}."); bodyParts.Renderers[i] = list; continue; } Renderer[] componentsInChildren2 = ((Component)val4).GetComponentsInChildren<Renderer>(true); foreach (Renderer val5 in componentsInChildren2) { if ((val5 is MeshRenderer || val5 is SkinnedMeshRenderer) && (!((Object)(object)val3 != (Object)null) || !((Component)val5).transform.IsChildOf(val3)) && UnderCosmeticParent(((Component)val5).transform, val4) && (i != 0 || (!UnderAny(((Component)val5).transform, bodyParts.Roots, 1) && (!((Object)(object)val2 != (Object)null) || !((Component)val5).transform.IsChildOf(val2))))) { list.Add(val5); } } bodyParts.Renderers[i] = list; } return bodyParts; } internal Vector3 Center(int index) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) List<Renderer> list = Renderers[index]; if (list.Count == 0) { if (!((Object)(object)Roots[index] != (Object)null)) { return Vector3.zero; } return Roots[index].position; } Vector3 val = Vector3.zero; foreach (Renderer item in list) { val += ((Component)item).transform.position; } return val / (float)list.Count; } private static bool UnderAny(Transform t, Transform[] roots, int from) { for (int i = from; i < roots.Length; i++) { if ((Object)(object)roots[i] != (Object)null && t.IsChildOf(roots[i])) { return true; } } return false; } private static bool UnderCosmeticParent(Transform t, Transform root) { Transform val = t; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { if (((Object)val).name.StartsWith("Cosmetic Parent")) { return true; } val = val.parent; } return false; } private static Transform Find(Transform[] all, string name) { foreach (Transform val in all) { if (((Object)val).name == name) { return val; } } return null; } } internal sealed class LimbConfig { internal readonly ConfigEntry<float> MinDamagePercent; internal readonly ConfigEntry<float> ArmZoneHeight; internal readonly ConfigEntry<float> OneLegSpeed; internal readonly ConfigEntry<float> OneLegJump; internal readonly ConfigEntry<float> NoLegsSpeed; internal readonly ConfigEntry<float> OneArmGrabStrength; internal readonly ConfigEntry<bool> OneArmBlocksRotate; internal readonly ConfigEntry<bool> DumpHierarchy; internal LimbConfig(ConfigFile cfg) { MinDamagePercent = cfg.Bind<float>("Trigger", "MinDamagePercent", 0.2f, "Andel av maxhälsan (0-1) som en enskild träff måste ta för att lemmen i träffzonen ska förloras."); ArmZoneHeight = cfg.Bind<float>("Trigger", "ArmZoneHeight", 0.5f, "Relativ höjd på kroppen (0 = fötter, 1 = topp) där armzonen börjar. Under = ben."); OneLegSpeed = cfg.Bind<float>("Legs", "OneLegSpeed", 0.6f, "Hastighetsmultiplikator med ett ben. Sprint är avstängd."); OneLegJump = cfg.Bind<float>("Legs", "OneLegJump", 0.6f, "Hoppkraftsmultiplikator med ett ben."); NoLegsSpeed = cfg.Bind<float>("Legs", "NoLegsSpeed", 0.6f, "Hastighetsmultiplikator utan ben (utöver tvingad crouch). Hopp och sprint är avstängda."); OneArmGrabStrength = cfg.Bind<float>("Arms", "OneArmGrabStrength", 0.5f, "Greppstyrkemultiplikator med en arm. Utan armar kan inget greppas."); OneArmBlocksRotate = cfg.Bind<bool>("Arms", "OneArmBlocksRotate", true, "Om rotation av greppade objekt är avstängd med en arm."); DumpHierarchy = cfg.Bind<bool>("Debug", "DumpHierarchy", false, "Skriver spelarmodellens hierarki till loggen (för att hitta lemmar till visuell fas)."); } } internal static class LimbNetwork { private const byte EventCode = 151; private static bool registered; internal static void EnsureRegistered() { if (!registered && PhotonNetwork.NetworkingClient != null) { PhotonNetwork.NetworkingClient.EventReceived += OnEvent; registered = true; } } internal static void Broadcast() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown if (SemiFunc.IsMultiplayer() && PhotonNetwork.InRoom) { PhotonNetwork.RaiseEvent((byte)151, (object)(int)LimbState.Local, new RaiseEventOptions { Receivers = (ReceiverGroup)0 }, SendOptions.SendReliable); } } private static void OnEvent(EventData e) { if (e.Code == 151 && e.CustomData is int lost) { LimbState.SetRemote(e.Sender, (Limb)lost); } } } internal sealed class LimbPart : MonoBehaviour { internal static readonly List<LimbPart> All = new List<LimbPart>(); private static readonly int HurtAmount = Shader.PropertyToID("_ColorOverlayAmount"); internal int OwnerViewID = -1; internal int Index = -1; internal PlayerAvatar Owner; internal PhysGrabObject Grab; internal bool Active; private PhotonView view; private bool visualsBuilt; internal Limb Limb => BodyParts.ToLimb(Index); private void Awake() { Grab = ((Component)this).GetComponent<PhysGrabObject>(); view = ((Component)this).GetComponent<PhotonView>(); All.Add(this); PhysGrabObjectImpactDetector component = ((Component)this).GetComponent<PhysGrabObjectImpactDetector>(); if ((Object)(object)component != (Object)null) { component.destroyDisable = true; } object[] array = (((Object)(object)view != (Object)null) ? view.InstantiationData : null); if (array != null && array.Length == 2 && array[0] is int ownerViewID && array[1] is int index) { Init(ownerViewID, index); } } private void OnDestroy() { All.Remove(this); } internal void Init(int ownerViewID, int index) { //IL_007d: 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_0051: Unknown result type (might be due to invalid IL or missing references) OwnerViewID = ownerViewID; Index = index; ((Object)this).name = $"RepoLimbMod Part {index} ({ownerViewID})"; BoxCollider componentInChildren = ((Component)this).GetComponentInChildren<BoxCollider>(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.size = ((index == 0) ? new Vector3(0.45f, 0.5f, 0.35f) : ((index <= 2) ? new Vector3(0.15f, 0.4f, 0.15f) : new Vector3(0.18f, 0.45f, 0.18f))); } } private void Update() { if ((Object)(object)Owner == (Object)null && OwnerViewID > 0) { PhotonView val = PhotonView.Find(OwnerViewID); Owner = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<PlayerAvatar>() : null); } if (!visualsBuilt && (Object)(object)Owner != (Object)null) { BuildVisuals(); } if (!Active && (Object)(object)Grab != (Object)null && SemiFunc.IsMasterClientOrSingleplayer() && (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated) { Grab.OverrideDeactivate(0.1f); } } internal void Place(Vector3 position, Quaternion rotation) { //IL_0018: 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) Active = true; Grab.OverrideDeactivateReset(); Grab.Teleport(position, rotation); } internal void Hide() { Active = false; Grab.OverrideDeactivate(0.1f); } internal void ReleaseLocalGrab() { if ((Object)(object)Grab == (Object)null) { return; } foreach (PhysGrabber item in Grab.playerGrabbing.ToList()) { if ((Object)(object)item != (Object)null && item.isLocal) { item.ReleaseObject(view.ViewID, 0.25f); } } } private void BuildVisuals() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: 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_0205: Unknown result type (might be due to invalid IL or missing references) BodyParts bodyParts = ((Component)Owner).GetComponent<LimbVisuals>()?.Parts; if (bodyParts == null || Index < 0 || Index >= 5) { return; } visualsBuilt = true; Transform val = bodyParts.Roots[Index]; if ((Object)(object)val == (Object)null) { return; } GameObject val2 = new GameObject("Visual"); val2.transform.SetParent(((Component)this).transform, false); List<Transform> list = new List<Transform>(); foreach (Renderer item in bodyParts.Renderers[Index]) { MeshFilter val3 = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<MeshFilter>() : null); if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.sharedMesh == (Object)null)) { GameObject val4 = new GameObject(((Object)item).name); val4.transform.SetParent(val2.transform, false); val4.transform.localPosition = val.InverseTransformPoint(((Component)item).transform.position); val4.transform.localRotation = Quaternion.Inverse(val.rotation) * ((Component)item).transform.rotation; val4.transform.localScale = Divide(((Component)item).transform.lossyScale, val.lossyScale); val4.AddComponent<MeshFilter>().sharedMesh = val3.sharedMesh; ((Renderer)val4.AddComponent<MeshRenderer>()).sharedMaterials = CopyWithoutHurtFlash(item.sharedMaterials); list.Add(val4.transform); } } if (list.Count <= 0) { return; } Vector3 val5 = Vector3.zero; foreach (Transform item2 in list) { val5 += item2.localPosition; } val2.transform.localPosition = -val5 / (float)list.Count; } private static Material[] CopyWithoutHurtFlash(Material[] source) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown Material[] array = (Material[])(object)new Material[source.Length]; for (int i = 0; i < source.Length; i++) { if (!((Object)(object)source[i] == (Object)null)) { array[i] = new Material(source[i]); if (array[i].HasProperty(HurtAmount)) { array[i].SetFloat(HurtAmount, 0f); } } } return array; } private static Vector3 Divide(Vector3 a, Vector3 b) { //IL_0000: 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) //IL_000d: 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_001a: 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_0027: Unknown result type (might be due to invalid IL or missing references) return new Vector3(a.x / b.x, a.y / b.y, a.z / b.z); } } internal static class LimbParts { internal static LimbPart Find(PlayerAvatar owner, int index) { if ((Object)(object)owner == (Object)null) { return null; } int viewID = owner.photonView.ViewID; foreach (LimbPart item in LimbPart.All) { if ((Object)(object)item != (Object)null && item.OwnerViewID == viewID && item.Index == index) { return item; } } return null; } internal static bool HasParts(PlayerAvatar owner) { return (Object)(object)Find(owner, 0) != (Object)null; } internal static void SpawnAll() { if (!SemiFunc.IsMasterClientOrSingleplayer() || !SemiFunc.RunIsLevel() || (Object)(object)LimbPartTemplate.Template == (Object)null) { return; } foreach (PlayerAvatar player in GameDirector.instance.PlayerList) { if (!((Object)(object)player == (Object)null) && !HasParts(player)) { for (int i = 0; i < 5; i++) { LimbPartTemplate.Spawn(player, i); } } } } internal static void OnStateChanged(PlayerAvatar avatar, Limb before, Limb after) { if ((Object)(object)avatar == (Object)null) { return; } bool flag = SemiFunc.IsMasterClientOrSingleplayer(); for (int i = 1; i < 5; i++) { Limb limb = BodyParts.ToLimb(i); bool flag2 = (before & limb) != 0; bool flag3 = (after & limb) != 0; LimbPart limbPart = Find(avatar, i); if ((Object)(object)limbPart == (Object)null || flag2 == flag3) { continue; } if (flag3) { if (flag && !limbPart.Active && !avatar.deadSet) { PlaceFromBody(avatar, limbPart); } continue; } limbPart.ReleaseLocalGrab(); if (flag) { limbPart.Hide(); } } } internal static bool OnDeath(PlayerAvatar avatar) { if (!HasParts(avatar)) { return false; } if (SemiFunc.IsMasterClientOrSingleplayer()) { Limb limb = LimbState.Get(avatar); PlaceFromBody(avatar, Find(avatar, 0)); for (int i = 1; i < 5; i++) { LimbPart limbPart = Find(avatar, i); if ((limb & BodyParts.ToLimb(i)) == 0 && (Object)(object)limbPart != (Object)null && !limbPart.Active) { PlaceFromBody(avatar, limbPart); } } } return true; } internal static void OnRevive(PlayerAvatar avatar) { if (HasParts(avatar)) { LimbPart limbPart = Find(avatar, 0); limbPart.ReleaseLocalGrab(); if (SemiFunc.IsMasterClientOrSingleplayer()) { limbPart.Hide(); } if (!SemiFunc.IsMultiplayer() || avatar.photonView.IsMine) { Limb limb = ((Random.value < 0.5f) ? Limb.LeftArm : Limb.RightArm); Limb limb2 = ((Random.value < 0.5f) ? Limb.LeftLeg : Limb.RightLeg); LimbState.SetLocal(Limb.All & ~(limb | limb2)); Plugin.Log.LogInfo((object)$"Revive: fick tillbaka {limb} och {limb2}."); } } } private static void PlaceFromBody(PlayerAvatar avatar, LimbPart part) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) BodyParts bodyParts = ((Component)avatar).GetComponent<LimbVisuals>()?.Parts; if (!((Object)(object)part == (Object)null) && bodyParts != null && !((Object)(object)bodyParts.Roots[part.Index] == (Object)null)) { part.Place(bodyParts.Center(part.Index), bodyParts.Roots[part.Index].rotation); } } } internal static class LimbPartTemplate { internal const string PrefabId = "RepoLimbMod LimbPart"; private static readonly HashSet<string> Keep = new HashSet<string> { "Transform", "Rigidbody", "PhotonView", "PhotonTransformView", "PhysGrabObject", "PhysGrabObjectImpactDetector", "RoomVolumeCheck", "NotValuableObject" }; internal static GameObject Template { get; private set; } internal static void Register(LevelGenerator generator) { if ((Object)(object)Template == (Object)null) { if ((Object)(object)generator.PlayerDeathHeadPrefab == (Object)null) { Plugin.Log.LogError((object)"PlayerDeathHeadPrefab saknas, kroppsdelar kan inte skapas."); return; } Template = Build(generator.PlayerDeathHeadPrefab); } RunManager.instance.multiplayerPool.ResourceCache["RepoLimbMod LimbPart"] = Template; } private static GameObject Build(GameObject head) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("RepoLimbMod Templates"); val.SetActive(false); Object.DontDestroyOnLoad((Object)(object)val); GameObject val2 = Object.Instantiate<GameObject>(head, val.transform); ((Object)val2).name = "RepoLimbMod LimbPart"; for (int num = val2.transform.childCount - 1; num >= 0; num--) { Object.DestroyImmediate((Object)(object)((Component)val2.transform.GetChild(num)).gameObject); } List<string> list = new List<string>(); Component[] components; for (int i = 0; i < 4; i++) { components = val2.GetComponents<Component>(); foreach (Component val3 in components) { if (!((Object)(object)val3 == (Object)null) && !Keep.Contains(((object)val3).GetType().Name)) { string name = ((object)val3).GetType().Name; Object.DestroyImmediate((Object)(object)val3); if ((Object)(object)val3 == (Object)null && !list.Contains(name)) { list.Add(name); } } } } PhotonView component = val2.GetComponent<PhotonView>(); if ((Object)(object)component != (Object)null && component.ObservedComponents != null) { component.ObservedComponents.RemoveAll((Component c) => (Object)(object)c == (Object)null); } GameObject val4 = new GameObject("Collider"); val4.transform.SetParent(val2.transform, false); val4.tag = "Phys Grab Object"; val4.layer = LayerMask.NameToLayer("PhysGrabObject"); val4.AddComponent<BoxCollider>().size = Vector3.one * 0.3f; val4.AddComponent<PhysGrabObjectCollider>(); val2.AddComponent<LimbPart>(); StringBuilder stringBuilder = new StringBuilder("Kroppsdelsmall skapad. Borttaget: "); stringBuilder.Append(string.Join(", ", list)).Append(". Kvar: "); List<string> list2 = new List<string>(); components = val2.GetComponents<Component>(); foreach (Component val5 in components) { list2.Add(((object)val5).GetType().Name); } stringBuilder.Append(string.Join(", ", list2)); Plugin.Log.LogInfo((object)stringBuilder.ToString()); return val2; } internal static LimbPart Spawn(PlayerAvatar owner, int index) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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) Vector3 physDisabledPosition = AssetManager.instance.physDisabledPosition; if (SemiFunc.IsMultiplayer()) { GameObject val = PhotonNetwork.Instantiate("RepoLimbMod LimbPart", physDisabledPosition, Quaternion.identity, (byte)0, new object[2] { owner.photonView.ViewID, index }); if (!((Object)(object)val != (Object)null)) { return null; } return val.GetComponent<LimbPart>(); } LimbPart component = Object.Instantiate<GameObject>(Template, physDisabledPosition, Quaternion.identity).GetComponent<LimbPart>(); component.Init(owner.photonView.ViewID, index); component.Owner = owner; return component; } } [Flags] internal enum Limb { None = 0, LeftArm = 1, RightArm = 2, LeftLeg = 4, RightLeg = 8, Arms = 3, Legs = 0xC, All = 0xF } internal static class LimbState { internal static Limb Local; private static readonly Dictionary<int, Limb> remote = new Dictionary<int, Limb>(); internal static Vector3? PendingHitPoint; internal static int LegsLost => Count(Local & Limb.Legs); internal static int ArmsLost => Count(Local & Limb.Arms); internal static Limb Get(PlayerAvatar avatar) { if ((Object)(object)avatar == (Object)null) { return Limb.None; } if (!SemiFunc.IsMultiplayer() || avatar.photonView.IsMine) { return Local; } Player owner = avatar.photonView.Owner; if (owner == null || !remote.TryGetValue(owner.ActorNumber, out var value)) { return Limb.None; } return value; } internal static void SetRemote(int actorNumber, Limb lost) { remote.TryGetValue(actorNumber, out var value); remote[actorNumber] = lost; if (value != lost) { LimbParts.OnStateChanged(FindByActor(actorNumber), value, lost); } } internal static void SetLocal(Limb lost) { Limb local = Local; Local = lost; if (local != lost) { LimbParts.OnStateChanged(PlayerAvatar.instance, local, lost); } LimbNetwork.Broadcast(); } private static PlayerAvatar FindByActor(int actorNumber) { foreach (PlayerAvatar player in GameDirector.instance.PlayerList) { Player val = (((Object)(object)player != (Object)null) ? player.photonView.Owner : null); if (val != null && val.ActorNumber == actorNumber) { return player; } } return null; } internal static int Count(Limb limbs) { int num = 0; for (int num2 = (int)limbs; num2 != 0; num2 &= num2 - 1) { num++; } return num; } internal static void ResetAll() { bool num = Local != Limb.None; remote.Clear(); if (num) { Plugin.Log.LogInfo((object)"Lemmar återställda."); SetLocal(Limb.None); } } internal static void OnDamaged(int damage, int maxHealth, Vector3? hitPoint) { //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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) if (!hitPoint.HasValue) { return; } Vector3 valueOrDefault = hitPoint.GetValueOrDefault(); if ((float)damage < (float)maxHealth * Plugin.Cfg.MinDamagePercent.Value) { return; } PlayerAvatar instance = PlayerAvatar.instance; if (!((Object)(object)instance == (Object)null) && TryGetBodyBounds(instance, out var bounds)) { Limb limb = LimbAt(valueOrDefault, bounds, ((Component)instance.playerAvatarVisuals).transform); if ((Local & limb) == 0) { Plugin.Log.LogInfo((object)$"Förlorade {limb} (skada {damage}/{maxHealth}, träffpunkt {valueOrDefault}). Status: {Local | limb}"); SetLocal(Local | limb); } } } internal static bool TryGetBodyBounds(PlayerAvatar avatar, out Bounds bounds) { //IL_0001: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); BodyParts bodyParts = ((!((Object)(object)avatar != (Object)null)) ? null : ((Component)avatar).GetComponent<LimbVisuals>()?.Parts); if (bodyParts == null) { return false; } bool flag = false; for (int i = 0; i < 5; i++) { foreach (Renderer item in bodyParts.Renderers[i]) { object obj; if (!((Object)(object)item != (Object)null)) { obj = null; } else { MeshFilter component = ((Component)item).GetComponent<MeshFilter>(); obj = ((component != null) ? component.sharedMesh : null); } Mesh val = (Mesh)obj; if ((Object)(object)val == (Object)null) { continue; } Bounds bounds2 = val.bounds; for (int j = 0; j < 8; j++) { Vector3 val2 = ((Component)item).transform.TransformPoint(((Bounds)(ref bounds2)).center + Vector3.Scale(((Bounds)(ref bounds2)).extents, new Vector3((float)(((j & 1) != 0) ? 1 : (-1)), (float)(((j & 2) != 0) ? 1 : (-1)), (float)(((j & 4) != 0) ? 1 : (-1))))); if (flag) { ((Bounds)(ref bounds)).Encapsulate(val2); continue; } bounds = new Bounds(val2, Vector3.zero); flag = true; } } } return flag; } private static Limb LimbAt(Vector3 hit, Bounds bounds, Transform body) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_0038: 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) bool num = Mathf.InverseLerp(((Bounds)(ref bounds)).min.y, ((Bounds)(ref bounds)).max.y, hit.y) >= Plugin.Cfg.ArmZoneHeight.Value; float x = body.InverseTransformPoint(hit).x; bool flag = ((Mathf.Abs(x) < 0.05f) ? (Random.value < 0.5f) : (x < 0f)); if (num) { if (!flag) { return Limb.RightArm; } return Limb.LeftArm; } if (!flag) { return Limb.RightLeg; } return Limb.LeftLeg; } } internal sealed class LimbVisuals : MonoBehaviour { private PlayerAvatar avatar; private Limb shown; internal BodyParts Parts { get; private set; } internal void Init(PlayerAvatar playerAvatar) { avatar = playerAvatar; if ((Object)(object)avatar.playerAvatarVisuals == (Object)null) { Plugin.Log.LogWarning((object)"PlayerAvatarVisuals saknas, lemmar kan inte döljas."); } else { Parts = BodyParts.Collect(avatar.playerAvatarVisuals); } } private void LateUpdate() { if ((Object)(object)avatar == (Object)null || Parts == null) { return; } Limb limb = LimbState.Get(avatar); for (int i = 1; i < 5; i++) { Limb limb2 = BodyParts.ToLimb(i); if ((limb & limb2) != Limb.None) { foreach (Renderer item in Parts.Renderers[i]) { if ((Object)(object)item != (Object)null && item.enabled) { item.enabled = false; } } } else { if ((shown & limb2) == 0) { continue; } foreach (Renderer item2 in Parts.Renderers[i]) { if ((Object)(object)item2 != (Object)null) { item2.enabled = true; } } } } shown = limb; } } [HarmonyPatch(typeof(LevelGenerator), "Start")] internal static class LevelGeneratorStartPatch { private static void Postfix(LevelGenerator __instance) { LimbPartTemplate.Register(__instance); } } [HarmonyPatch(typeof(LevelGenerator), "PlayerSpawn")] internal static class PlayerSpawnPatch { private static void Postfix() { LimbParts.SpawnAll(); } } [HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathDone")] internal static class DeathDonePatch { private static void Prefix(PlayerAvatar __instance) { if (!__instance.isDisabled) { LimbParts.OnDeath(__instance); } } } [HarmonyPatch(typeof(PlayerDeathEffects), "Trigger")] internal static class DeathEffectsPatch { private static bool Prefix(PlayerDeathEffects __instance) { PlayerAvatar val = (((Object)(object)__instance.playerAvatarVisuals != (Object)null) ? __instance.playerAvatarVisuals.playerAvatar : null); if (!((Object)(object)val == (Object)null)) { return !LimbParts.HasParts(val); } return true; } } [HarmonyPatch(typeof(PlayerAvatar), "ReviveRPC")] internal static class RevivePatch { private static void Postfix(PlayerAvatar __instance) { if (!__instance.deadSet) { LimbParts.OnRevive(__instance); } } } [HarmonyPatch(typeof(PlayerController), "Update")] internal static class ReattachPatch { private const float LookRange = 4.5f; private static void Postfix() { PlayerAvatar instance = PlayerAvatar.instance; if ((Object)(object)instance == (Object)null || instance.deadSet || (Object)(object)ItemInfoUI.instance == (Object)null) { return; } LimbPart limbPart = HeldPart() ?? LookedAtOwnPart(instance); if ((Object)(object)limbPart == (Object)null || (Object)(object)limbPart.Owner == (Object)null) { return; } string text = DisplayName(limbPart.Index); if (!((Object)(object)limbPart.Owner == (Object)(object)instance)) { ItemInfoUI.instance.ItemInfoText((ItemAttributes)null, limbPart.Owner.playerName + "'s " + text, false); } else if (limbPart.Index != 0 && (LimbState.Local & limbPart.Limb) != Limb.None) { string text2 = SemiFunc.InputDisplayReplaceTags("[interact]", "<u><b>", "</b></u>"); ItemInfoUI.instance.ItemInfoText((ItemAttributes)null, "Re-Attach " + text + " <color=#FFFFFF>[" + text2 + "]</color>", false); if (PlayerController.instance.InputDisableTimer <= 0f && SemiFunc.InputDown((InputKey)2)) { Plugin.Log.LogInfo((object)$"Monterade tillbaka {limbPart.Limb}."); LimbState.SetLocal(LimbState.Local & ~limbPart.Limb); } } } private static LimbPart HeldPart() { foreach (LimbPart item in LimbPart.All) { if ((Object)(object)item != (Object)null && (Object)(object)item.Grab != (Object)null && item.Grab.grabbedLocal) { return item; } } return null; } private static LimbPart LookedAtOwnPart(PlayerAvatar avatar) { //IL_0020: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (LimbState.Local == Limb.None) { return null; } Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return null; } RaycastHit[] array = Physics.RaycastAll(((Component)main).transform.position, ((Component)main).transform.forward, 4.5f, -1, (QueryTriggerInteraction)1); for (int i = 0; i < array.Length; i++) { RaycastHit val = array[i]; LimbPart componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<LimbPart>(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.Owner == (Object)(object)avatar) { return componentInParent; } } return null; } private static string DisplayName(int index) { return index switch { 1 => "Left Arm", 2 => "Right Arm", 3 => "Left Leg", 4 => "Right Leg", _ => "Torso", }; } } [HarmonyPatch(typeof(PlayerHealth), "Hurt")] internal static class HurtPatch { private static void Prefix(PlayerHealth __instance, int enemyIndex, out int __state) { //IL_0049: 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) __state = __instance.health; if (!LimbState.PendingHitPoint.HasValue && enemyIndex >= 0) { Enemy val = SemiFunc.EnemyGetFromIndex(enemyIndex); if ((Object)(object)val != (Object)null) { LimbState.PendingHitPoint = (((Object)(object)val.CenterTransform != (Object)null) ? val.CenterTransform.position : ((Component)val).transform.position); } } } private static void Postfix(PlayerHealth __instance, int enemyIndex, int __state) { //IL_005f: 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) int num = __state - __instance.health; Vector3? pendingHitPoint = LimbState.PendingHitPoint; LimbState.PendingHitPoint = null; if (num > 0) { Plugin.Log.LogInfo((object)string.Format("Träff: {0}/{1} HP, fiende {2}, träffpunkt {3}, hälsa kvar {4}.", num, __instance.maxHealth, enemyIndex, (pendingHitPoint.HasValue ? ((object)pendingHitPoint.GetValueOrDefault()/*cast due to .constrained prefix*/).ToString() : null) ?? "saknas", __instance.health)); if (__instance.health > 0 && !__instance.playerAvatar.deadSet && SemiFunc.RunIsLevel()) { LimbState.OnDamaged(num, __instance.maxHealth, pendingHitPoint); } } } } [HarmonyPatch(typeof(PlayerHealth), "HurtOtherRPC")] internal static class HurtOtherPatch { private static void Prefix(PlayerHealth __instance, Vector3 hurtPosition) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_002b: Unknown result type (might be due to invalid IL or missing references) if (!(hurtPosition == Vector3.zero) && !(Vector3.Distance(hurtPosition, ((Component)__instance.playerAvatar).transform.position) < 0.1f)) { LimbState.PendingHitPoint = hurtPosition; } } private static void Postfix() { LimbState.PendingHitPoint = null; } } [HarmonyPatch(typeof(HurtCollider), "PlayerHurt")] internal static class HurtColliderPatch { private static void Prefix(HurtCollider __instance, PlayerAvatar _player) { //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) //IL_003c: 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) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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) if (!((Object)(object)__instance.Collider == (Object)null) && (!SemiFunc.IsMultiplayer() || _player.photonView.IsMine) && LimbState.TryGetBodyBounds(_player, out var bounds)) { Vector3 center = ((Bounds)(ref bounds)).center; Vector3 val = __instance.Collider.ClosestPoint(center); Vector3 value; if (!(val == center)) { value = val; } else { Bounds bounds2 = __instance.Collider.bounds; value = ((Bounds)(ref bounds2)).center; } LimbState.PendingHitPoint = value; } } private static void Postfix() { LimbState.PendingHitPoint = null; } } [HarmonyPatch(typeof(PlayerAvatar), "Start")] internal static class AvatarStartPatch { private static bool dumped; private static void Postfix(PlayerAvatar __instance) { LimbNetwork.EnsureRegistered(); if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).GetComponent<LimbVisuals>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<LimbVisuals>().Init(__instance); } if (!SemiFunc.IsMultiplayer() || __instance.photonView.IsMine) { if (SemiFunc.RunIsShop() || SemiFunc.MenuLevel() || SemiFunc.RunIsArena()) { LimbState.ResetAll(); } else { LimbNetwork.Broadcast(); } if (!dumped && Plugin.Cfg.DumpHierarchy.Value && (Object)(object)__instance.playerAvatarVisuals != (Object)null) { dumped = true; StringBuilder stringBuilder = new StringBuilder("Spelarmodellens hierarki:\n"); Dump(((Component)__instance.playerAvatarVisuals).transform, 0, stringBuilder); Plugin.Log.LogInfo((object)stringBuilder.ToString()); } } } private static void Dump(Transform t, int depth, StringBuilder sb) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown sb.Append(' ', depth * 2).Append(((Object)t).name); if ((Object)(object)((Component)t).GetComponent<Renderer>() != (Object)null) { sb.Append(" [Renderer]"); } sb.Append('\n'); foreach (Transform item in t) { Dump(item, depth + 1, sb); } } } [HarmonyPatch(typeof(PlayerController), "FixedUpdate")] internal static class ControllerFixedUpdatePatch { private static void Prefix(PlayerController __instance, out float __state) { __state = __instance.JumpForce; int legsLost = LimbState.LegsLost; if (legsLost != 0) { __instance.toggleSprint = false; if (legsLost >= 2) { __instance.CrouchOverride(0.2f); } else { __instance.JumpForce *= Plugin.Cfg.OneLegJump.Value; } } } private static void Postfix(PlayerController __instance, float __state) { __instance.JumpForce = __state; } } [HarmonyPatch(typeof(PlayerController), "OverrideSpeedLogic")] internal static class SpeedPatch { private static bool applied; private static void Postfix(PlayerController __instance) { if (!(__instance.overrideTimeScaleTimer > 0f)) { float num = SpeedMultiplier(); if (!(num >= 1f) || applied) { float num2 = ((__instance.overrideSpeedTimer > 0f) ? __instance.overrideSpeedMultiplier : 1f); __instance.MoveSpeed = __instance.playerOriginalMoveSpeed * num2 * num; __instance.SprintSpeed = __instance.playerOriginalSprintSpeed * num2 * num; __instance.CrouchSpeed = __instance.playerOriginalCrouchSpeed * num2 * num; applied = num < 1f; } } } private static float SpeedMultiplier() { return LimbState.LegsLost switch { 0 => 1f, 1 => Plugin.Cfg.OneLegSpeed.Value, _ => Plugin.Cfg.NoLegsSpeed.Value, }; } } [HarmonyPatch(typeof(PhysGrabber), "Update")] internal static class GrabberUpdatePatch { private static void Prefix(PhysGrabber __instance) { int num = LimbState.Count(LimbState.Get(__instance.playerAvatar) & Limb.Arms); if (num == 1) { __instance.OverrideGrabStrength(__instance.grabStrength * Plugin.Cfg.OneArmGrabStrength.Value, 0.2f); } else if (num >= 2 && __instance.isLocal) { __instance.toggleGrab = false; } } } [HarmonyPatch] internal static class InputPatch { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(InputManager), "KeyHold", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(InputManager), "KeyDown", (Type[])null, (Type[])null); } private static bool Prefix(InputKey key, ref bool __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (!Blocks(key)) { return true; } __result = false; return false; } private static bool Blocks(InputKey key) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 if (LimbState.Local == Limb.None) { return false; } PlayerAvatar instance = PlayerAvatar.instance; if ((Object)(object)instance == (Object)null || instance.deadSet) { return false; } if ((int)key <= 10) { if ((int)key == 1) { return LimbState.LegsLost >= 2; } if ((int)key == 10) { return LimbState.ArmsLost >= 2; } } else { if ((int)key == 11) { if (LimbState.ArmsLost == 1) { return Plugin.Cfg.OneArmBlocksRotate.Value; } return false; } if ((int)key == 15) { return LimbState.LegsLost >= 1; } } return false; } } [BepInPlugin("kinglir.repolimbmod", "RepoLimbMod", "0.2.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string Guid = "kinglir.repolimbmod"; public const string Name = "RepoLimbMod"; public const string Version = "0.2.1"; internal static ManualLogSource Log; internal static LimbConfig Cfg; private void Awake() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Cfg = new LimbConfig(((BaseUnityPlugin)this).Config); new Harmony("kinglir.repolimbmod").PatchAll(); Log.LogInfo((object)"RepoLimbMod 0.2.1 laddad."); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }