using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using PluginConfig.API; using PluginConfig.API.Decorators; using PluginConfig.API.Fields; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("TokenSkulls")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("TokenSkulls")] [assembly: AssemblyTitle("TokenSkulls")] [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 TokenSkulls { internal sealed class ConfigUI { private const float PosRange = 5f; private const float RotRange = 180f; private const float ScaleMin = 0.05f; private const float ScaleMax = 10f; private const string IconFile = "icon.png"; private PluginConfigurator config; private BoolField enabledField; public Action OnEnabledChanged; public Action OnPlacementChanged; public bool IsEnabled => enabledField == null || enabledField.value; public void Setup() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown config = PluginConfigurator.Create("Token Skulls", "com.scout.tokenskulls"); Sprite val = LoadIcon("icon.png"); if ((Object)(object)val != (Object)null) { config.image = val; } enabledField = new BoolField(config.rootPanel, "Enabled", "enabled", true); ConfigDivision settings = new ConfigDivision(config.rootPanel, "settings"); ((ConfigField)settings).hidden = !enabledField.value; enabledField.onValueChange += (BoolValueChangeEventDelegate)delegate(BoolValueChangeEvent e) { ((ConfigField)settings).hidden = !e.value; OnEnabledChanged?.Invoke(e.value); }; ConfigPanel panel = new ConfigPanel((ConfigPanel)(object)settings, "World Skull Placement", "world_settings"); BuildPlacement(panel, "world", TokenSkullsPlugin.World); ConfigPanel panel2 = new ConfigPanel((ConfigPanel)(object)settings, "Held Skull Placement", "held_settings"); BuildPlacement(panel2, "held", TokenSkullsPlugin.Held); } private Sprite LoadIcon(string fileName) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_006a: 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) string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), fileName); if (!File.Exists(path)) { TokenSkullsPlugin.Log.LogWarning((object)"No icon which how???"); return null; } byte[] array = File.ReadAllBytes(path); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, array); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } private void BuildPlacement(ConfigPanel panel, string prefix, TokenSkullsPlugin.Placement p) { //IL_0016: 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_018e: Unknown result type (might be due to invalid IL or missing references) new ConfigHeader(panel, "Position Offset", 20); Slider(panel, "Position X", prefix + "_pos_x", p.posX, -5f, 5f, 2, delegate(float v) { p.posX = v; }); Slider(panel, "Position Y", prefix + "_pos_y", p.posY, -5f, 5f, 2, delegate(float v) { p.posY = v; }); Slider(panel, "Position Z", prefix + "_pos_z", p.posZ, -5f, 5f, 2, delegate(float v) { p.posZ = v; }); new ConfigHeader(panel, "Rotation Offset", 20); Slider(panel, "Rotation X", prefix + "_rot_x", p.rotX, -180f, 180f, 1, delegate(float v) { p.rotX = v; }); Slider(panel, "Rotation Y", prefix + "_rot_y", p.rotY, -180f, 180f, 1, delegate(float v) { p.rotY = v; }); Slider(panel, "Rotation Z", prefix + "_rot_z", p.rotZ, -180f, 180f, 1, delegate(float v) { p.rotZ = v; }); new ConfigHeader(panel, "Size Multiplier", 20); Slider(panel, "Scale", prefix + "_scale", p.scale, 0.05f, 10f, 2, delegate(float v) { p.scale = v; }); } private void Slider(ConfigPanel panel, string label, string guid, float def, float min, float max, int decimals, Action apply) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown FloatSliderField val = new FloatSliderField(panel, label, guid, new Tuple(min, max), def, decimals); val.onValueChange += (OnValueChangeEventDelegate)delegate(FloatSliderValueChangeEvent e) { apply(e.newValue); OnPlacementChanged?.Invoke(); }; apply(val.value); } } [BepInPlugin("com.scout.tokenskulls", "Token Skulls", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class TokenSkullsPlugin : BaseUnityPlugin { private class Variant { public GameObject prefab; public Vector3 pos; public Quaternion rot; public Vector3 scale; } public class Placement { public float posX; public float posY; public float posZ; public float rotX; public float rotY; public float rotZ; public float scale = 1f; public Vector3 PosOffset => new Vector3(posX, posY, posZ); public Vector3 RotOffset => new Vector3(rotX, rotY, rotZ); } private class SkullTag : MonoBehaviour { public Transform clone; public Renderer hidden; public Variant variant; public bool wasHeld; } public const string GUID = "com.scout.tokenskulls"; public const string NAME = "Token Skulls"; public const string VERSION = "1.0.0"; private const string BundleFile = "tokenskulls.bundle"; private const string PrefabRed = "TokenSkullRed"; private const string PrefabBlue = "TokenSkullBlue"; private const string PrefabSingle = "TokenSkull"; public static readonly Placement World = new Placement(); public static readonly Placement Held = new Placement(); private static Variant redVariant; private static Variant blueVariant; private static bool modelReady; private static bool placementDirty; private static bool warnedNoAnchor; private static readonly List live = new List(); private static ConfigUI ui; internal static ManualLogSource Log; private Harmony harmony; private static bool IsEnabled => ui != null && ui.IsEnabled; private void Awake() { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ui = new ConfigUI(); ui.Setup(); ui.OnEnabledChanged = OnEnabledToggled; ui.OnPlacementChanged = delegate { placementDirty = true; }; LoadModel(); if (!modelReady) { Log.LogError((object)"Model never loaded"); return; } try { harmony = new Harmony("com.scout.tokenskulls"); harmony.PatchAll(); Log.LogInfo((object)"Patched Skull.Awake"); } catch (Exception arg) { Log.LogError((object)$"Harmony patch failed: {arg}"); } } private Variant TryLoad(AssetBundle bundle, string name) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_007d: Unknown result type (might be due to invalid IL or missing references) GameObject val = bundle.LoadAsset(name); if ((Object)(object)val == (Object)null) { return null; } if (val.GetComponentsInChildren(true).Length == 0) { Log.LogWarning((object)(name + " has no renderers anywhere")); return null; } return new Variant { prefab = val, pos = val.transform.localPosition, rot = val.transform.localRotation, scale = val.transform.localScale }; } private void LoadModel() { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string text = Path.Combine(directoryName, "tokenskulls.bundle"); if (!File.Exists(text)) { Log.LogError((object)("Bundle missing in " + text)); return; } AssetBundle val = AssetBundle.LoadFromFile(text); if ((Object)(object)val == (Object)null) { Log.LogError((object)"Bundle failed to load"); return; } redVariant = TryLoad(val, "TokenSkullRed"); blueVariant = TryLoad(val, "TokenSkullBlue"); Variant variant = TryLoad(val, "TokenSkull"); if (redVariant == null) { redVariant = variant ?? blueVariant; } if (blueVariant == null) { blueVariant = variant ?? redVariant; } if (redVariant == null || blueVariant == null) { Log.LogError((object)("No prefabs, need TokenSkullRed and TokenSkullBlue. Bundle only has: " + string.Join(", ", val.GetAllAssetNames()))); return; } if ((Object)(object)redVariant.prefab == (Object)(object)blueVariant.prefab) { Log.LogWarning((object)"Only one prefab found, add TokenSkullRed and TokenSkullBlue"); } modelReady = true; Log.LogInfo((object)("Loaded " + ((Object)redVariant.prefab).name + " and " + ((Object)blueVariant.prefab).name)); } internal static void OnSkullAwake(Skull skull) { if (modelReady && IsEnabled && Object.op_Implicit((Object)(object)skull)) { Dress(skull); } } private static void Dress(Skull skull) { Transform val = ((IEnumerable)((Component)skull).GetComponentsInChildren(true)).FirstOrDefault((Func)((Transform t) => ((Object)t).name == "NewSkull")); if (!Object.op_Implicit((Object)(object)val)) { if (!warnedNoAnchor) { warnedNoAnchor = true; Log.LogWarning((object)(((Object)skull).name + " has no NewSkull child")); } } else if (!Object.op_Implicit((Object)(object)((Component)val).GetComponent())) { Variant variant = (((Object)skull).name.ToLower().Contains("red") ? redVariant : blueVariant); SkullTag skullTag = ((Component)val).gameObject.AddComponent(); skullTag.variant = variant; skullTag.hidden = ((Component)val).GetComponent(); if (Object.op_Implicit((Object)(object)skullTag.hidden)) { skullTag.hidden.enabled = false; } GameObject val2 = Object.Instantiate(variant.prefab, val, false); ((Object)val2).name = "TokenSkullModel"; skullTag.clone = val2.transform; live.Add(skullTag); Place(skullTag, force: true); } } private static void Place(SkullTag tag, bool force) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) bool flag = ((Object)((Component)tag).transform.root).name == "Player"; if (force || flag != tag.wasHeld) { tag.wasHeld = flag; Placement placement = (flag ? Held : World); Variant variant = tag.variant; Transform clone = tag.clone; clone.localPosition = variant.pos + placement.PosOffset; clone.localRotation = variant.rot * Quaternion.Euler(placement.RotOffset); clone.localScale = variant.scale * placement.scale; } } private void Update() { if (live.Count == 0) { placementDirty = false; return; } bool force = placementDirty; for (int num = live.Count - 1; num >= 0; num--) { SkullTag skullTag = live[num]; if (!Object.op_Implicit((Object)(object)skullTag) || !Object.op_Implicit((Object)(object)skullTag.clone)) { live.RemoveAt(num); } else { if (Object.op_Implicit((Object)(object)skullTag.hidden) && skullTag.hidden.enabled) { skullTag.hidden.enabled = false; } Place(skullTag, force); } } placementDirty = false; } private static void OnEnabledToggled(bool on) { if (!modelReady) { return; } if (on) { Skull[] array = Object.FindObjectsOfType(); foreach (Skull val in array) { if (Object.op_Implicit((Object)(object)val)) { Dress(val); } } } else { RestoreAll(); } } private static void RestoreAll() { foreach (SkullTag item in live) { if (Object.op_Implicit((Object)(object)item)) { if (Object.op_Implicit((Object)(object)item.clone)) { Object.Destroy((Object)(object)((Component)item.clone).gameObject); } if (Object.op_Implicit((Object)(object)item.hidden)) { item.hidden.enabled = true; } Object.Destroy((Object)(object)item); } } live.Clear(); } } [HarmonyPatch(typeof(Skull), "Awake")] internal static class SkullAwakePatch { private static void Postfix(Skull __instance) { TokenSkullsPlugin.OnSkullAwake(__instance); } } }