using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem.Collections.Generic; using Mirror; using Rewired; using RewiredConsts; using StbImageSharp; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("BigWalk.Gourdwell")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.16.0")] [assembly: AssemblyInformationalVersion("1.0.16")] [assembly: AssemblyProduct("Gourdwell")] [assembly: AssemblyTitle("BigWalk.Gourdwell")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.16.0")] [module: UnverifiableCode] namespace BigWalk.Gourdwell; internal static class BackProfile { private const int Bins = 24; private const float SpineWidth = 0.35f; private static float[] _height; private static float _min; private static float _max; public static bool Ready => _height != null; public static float Min => _min; public static float Max => _max; public static void Build(Vector3[] verts, Vector3 forward, Vector3 up) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_0015: 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_001e: 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_003e: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) _height = null; if (verts == null || verts.Length == 0) { return; } Vector3 val = Vector3.Cross(up, forward); Vector3 normalized = ((Vector3)(ref val)).normalized; float num = float.MaxValue; float num2 = float.MinValue; float num3 = 0f; for (int i = 0; i < verts.Length; i++) { float num4 = Vector3.Dot(verts[i], forward); if (num4 < num) { num = num4; } if (num4 > num2) { num2 = num4; } num3 = Mathf.Max(num3, Mathf.Abs(Vector3.Dot(verts[i], normalized))); } if (num2 - num < 1E-05f) { return; } float num5 = num3 * 0.35f; float[] array = new float[24]; bool[] array2 = new bool[24]; float num6 = (num2 - num) / 24f; for (int j = 0; j < verts.Length; j++) { if (!(Mathf.Abs(Vector3.Dot(verts[j], normalized)) > num5)) { int num7 = Mathf.Clamp(Mathf.FloorToInt((Vector3.Dot(verts[j], forward) - num) / num6), 0, 23); float num8 = Vector3.Dot(verts[j], up); if (!array2[num7] || num8 > array[num7]) { array[num7] = num8; array2[num7] = true; } } } FillGaps(array, array2); Dilate(array); Smooth(array); _height = array; _min = num; _max = num2; } public static float HeightAt(float along) { if (_height == null) { return 0f; } float num = Mathf.Clamp01((along - _min) / (_max - _min)) * 23f; int num2 = Mathf.Clamp(Mathf.FloorToInt(num), 0, 23); int num3 = Mathf.Min(num2 + 1, 23); return Mathf.Lerp(_height[num2], _height[num3], num - (float)num2); } private static void FillGaps(float[] heights, bool[] seen) { int num = -1; for (int i = 0; i < 24; i++) { if (seen[i]) { num = i; } else if (num >= 0) { heights[i] = heights[num]; } } int num2 = -1; for (int num3 = 23; num3 >= 0; num3--) { if (seen[num3]) { num2 = num3; } else if (num2 >= 0 && num < 0) { heights[num3] = heights[num2]; } } } private static void Dilate(float[] heights) { float[] array = (float[])heights.Clone(); for (int i = 0; i < 24; i++) { int num = Mathf.Max(i - 1, 0); int num2 = Mathf.Min(i + 1, 23); heights[i] = Mathf.Max(array[num], Mathf.Max(array[i], array[num2])); } } private static void Smooth(float[] heights) { float[] array = (float[])heights.Clone(); for (int i = 1; i < 23; i++) { heights[i] = (array[i - 1] + array[i] * 2f + array[i + 1]) * 0.25f; } } } internal static class GourdAssets { public static Mesh Mesh; public static Texture2D Texture; public static Material Material; public static AudioClip ThemeClip; public static AudioClip PurrClip; public static Texture2D WhiskerTexture; public static Material WhiskerMaterial; public static Material[] SubMeshMaterials; public static Vector3[] BaseVertices; public static Vector3[] BaseNormals; public static bool VisualsReady { get { if ((Object)(object)Mesh != (Object)null && (Object)(object)Material != (Object)null) { return (Object)(object)Texture != (Object)null; } return false; } } public static bool AudioReady => (Object)(object)ThemeClip != (Object)null; } internal static class GourdPet { private struct Squish { public Transform Target; public Vector3 BaseScale; public Vector3 LocalUp; public float StartedAt; } public const float Duration = 0.5f; private const float SquashAmount = 0.16f; private const float BulgeAmount = 0.08f; private static readonly Dictionary Active = new Dictionary(); public static void Pet(int gourdId, Transform visual, Vector3 localUp) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)visual == (Object)null)) { if (!Active.TryGetValue(gourdId, out var value) || (Object)(object)value.Target != (Object)(object)visual) { value = new Squish { Target = visual, BaseScale = visual.localScale }; } value.LocalUp = localUp; value.StartedAt = Time.unscaledTime; Active[gourdId] = value; } } public static void Tick() { //IL_00b9: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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) if (Active.Count == 0) { return; } List list = null; foreach (KeyValuePair item in Active) { Squish value = item.Value; if ((Object)(object)value.Target == (Object)null) { if (list == null) { list = new List(); } list.Add(item.Key); continue; } float num = (Time.unscaledTime - value.StartedAt) / 0.5f; try { if (num >= 1f) { value.Target.localScale = value.BaseScale; if (list == null) { list = new List(); } list.Add(item.Key); } else { float k = Mathf.Sin(Mathf.Clamp01(num) * (float)Math.PI); value.Target.localScale = Vector3.Scale(value.BaseScale, Factor(value.LocalUp, k)); } } catch { if (list == null) { list = new List(); } list.Add(item.Key); } } if (list != null) { for (int i = 0; i < list.Count; i++) { Active.Remove(list[i]); } } } private static Vector3 Factor(Vector3 localUp, float k) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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) float num = 1f - 0.16f * k; float num2 = 1f + 0.08f * k; return new Vector3(Mathf.Lerp(num2, num, Mathf.Abs(localUp.x)), Mathf.Lerp(num2, num, Mathf.Abs(localUp.y)), Mathf.Lerp(num2, num, Mathf.Abs(localUp.z))); } } internal static class GourdVisual { private struct Tracked { public Renderer Renderer; public Material[] Materials; } private static readonly Dictionary TrackedByGourd = new Dictionary(); private static readonly MaterialPropertyBlock Block = new MaterialPropertyBlock(); private static readonly string[] AlbedoProps = new string[2] { "_BaseMap", "_MainTex" }; private static readonly string[] TintProps = new string[2] { "_BaseColor", "_Color" }; public static Transform GetRoot(RewardGourd gourd) { if ((Object)(object)gourd == (Object)null) { return null; } try { Prop prop = gourd.prop; if ((Object)(object)prop != (Object)null && (Object)(object)((Component)prop).transform != (Object)null) { return ((Component)prop).transform; } } catch { } try { return ((Component)gourd).transform; } catch { return null; } } public static int SwapInPlace(RewardGourd gourd, Mesh maxwellMesh, Material fallbackMaterial, Texture2D texture, Material whiskerTemplate, out string detail) { detail = "init"; if ((Object)(object)gourd == (Object)null || (Object)(object)maxwellMesh == (Object)null || (Object)(object)texture == (Object)null) { detail = "null-args"; return 0; } Transform root = GetRoot(gourd); if ((Object)(object)root == (Object)null) { detail = "no-root"; return 0; } detail = "root=" + ((Object)root).name; NeutralizePropertyBlockHelper(gourd); if (!TryFindTarget(root, out var meshFilter, out var skin, out var target, out var _, out var swapName, ref detail)) { return 0; } try { if ((Object)(object)meshFilter != (Object)null) { meshFilter.sharedMesh = maxwellMesh; } else if ((Object)(object)skin != (Object)null) { skin.sharedMesh = maxwellMesh; } } catch (Exception ex) { detail = detail + " mesh-assign-failed:" + ex.Message; return 0; } Material val = CreateUvLitMaterial(fallbackMaterial, texture); if ((Object)(object)val == (Object)null) { detail += " no-material"; return 0; } Material[] array = BuildMaterials(maxwellMesh, val, whiskerTemplate); Paint(target, array, texture); MeshRenderer val2 = (MeshRenderer)(object)((target is MeshRenderer) ? target : null); if (val2 != null) { HideOtherMeshRenderers(root, val2); } TrackedByGourd[((Object)gourd).GetInstanceID()] = new Tracked { Renderer = target, Materials = array }; detail = detail + " swapped='" + swapName + "' shader='" + ((Object)val.shader).name + "' submeshes=" + array.Length; return 1; } private static Material[] BuildMaterials(Mesh mesh, Material body, Material whiskerTemplate) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown int num = 1; try { num = Mathf.Max(1, mesh.subMeshCount); } catch { num = 1; } Material[] array = (Material[])(object)new Material[num]; array[0] = body; for (int i = 1; i < num; i++) { Material val = null; if ((Object)(object)whiskerTemplate != (Object)null) { try { val = new Material(whiskerTemplate) { name = "Gourdwell_Whiskers", hideFlags = (HideFlags)61 }; } catch { val = null; } } array[i] = val ?? body; } return array; } private static Material CreateUvLitMaterial(Material fallback, Texture2D texture) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown string[] array = new string[3] { "Universal Render Pipeline/Lit", "Universal Render Pipeline/Simple Lit", "Universal Render Pipeline/Unlit" }; Material val = null; for (int i = 0; i < array.Length; i++) { Shader val2 = Shader.Find(array[i]); if (!((Object)(object)val2 == (Object)null)) { try { val = new Material(val2); } catch { val = null; continue; } break; } } if ((Object)(object)val == (Object)null && (Object)(object)fallback != (Object)null && (Object)(object)fallback.shader != (Object)null && ((Object)fallback.shader).name != null && ((Object)fallback.shader).name.IndexOf("Better Lit", StringComparison.OrdinalIgnoreCase) < 0) { try { val = new Material(fallback); } catch { val = null; } } if ((Object)(object)val == (Object)null) { return null; } ((Object)val).name = "Gourdwell_Dingus_UV"; ((Object)val).hideFlags = (HideFlags)61; try { if (val.HasProperty("_Surface")) { val.SetFloat("_Surface", 0f); } if (val.HasProperty("_Blend")) { val.SetFloat("_Blend", 0f); } if (val.HasProperty("_AlphaClip")) { val.SetFloat("_AlphaClip", 0f); } if (val.HasProperty("_ZWrite")) { val.SetFloat("_ZWrite", 1f); } if (val.HasProperty("_Cull")) { val.SetFloat("_Cull", 2f); } if (val.HasProperty("_Metallic")) { val.SetFloat("_Metallic", 0f); } if (val.HasProperty("_Smoothness")) { val.SetFloat("_Smoothness", 0.35f); } val.renderQueue = 2000; val.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); val.DisableKeyword("_ALPHATEST_ON"); } catch { } ApplyDingus(val, texture); return val; } public static Transform GetVisual(RewardGourd gourd) { if ((Object)(object)gourd == (Object)null) { return null; } try { if (!TrackedByGourd.TryGetValue(((Object)gourd).GetInstanceID(), out var value)) { return null; } if ((Object)(object)value.Renderer == (Object)null) { return null; } return ((Component)value.Renderer).transform; } catch { return null; } } public static void MaintainAll(Texture2D texture) { if (TrackedByGourd.Count == 0 || (Object)(object)texture == (Object)null) { return; } List list = null; foreach (KeyValuePair item in TrackedByGourd) { Tracked value = item.Value; if ((Object)(object)value.Renderer == (Object)null || value.Materials == null || value.Materials.Length == 0 || (Object)(object)value.Materials[0] == (Object)null) { if (list == null) { list = new List(); } list.Add(item.Key); } else { try { Paint(value.Renderer, value.Materials, texture); } catch { } } } if (list != null) { for (int i = 0; i < list.Count; i++) { TrackedByGourd.Remove(list[i]); } } } private static bool TryFindTarget(Transform root, out MeshFilter meshFilter, out SkinnedMeshRenderer skin, out Renderer target, out Material donor, out string swapName, ref string detail) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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) meshFilter = null; skin = null; target = null; donor = null; swapName = "?"; MeshFilter val = null; float num = -1f; int num2 = 0; try { Il2CppArrayBase componentsInChildren = ((Component)root).GetComponentsInChildren(true); if (componentsInChildren != null) { num2 = componentsInChildren.Length; for (int i = 0; i < componentsInChildren.Length; i++) { MeshFilter val2 = componentsInChildren[i]; if ((Object)(object)val2 == (Object)null) { continue; } float num3 = 0f; try { if ((Object)(object)val2.sharedMesh != (Object)null) { Bounds bounds = val2.sharedMesh.bounds; Vector3 size = ((Bounds)(ref bounds)).size; num3 = ((Vector3)(ref size)).sqrMagnitude; } } catch { num3 = 0f; } if ((Object)(object)val == (Object)null || num3 > num) { num = num3; val = val2; } } } } catch (Exception ex) { detail = detail + " filter-ex=" + ex.Message; } detail = detail + " filters=" + num2; if ((Object)(object)val != (Object)null) { meshFilter = val; target = (Renderer)(object)((Component)val).GetComponent(); if ((Object)(object)target != (Object)null) { donor = target.sharedMaterial; } swapName = ((Object)val).name; return (Object)(object)target != (Object)null; } try { Il2CppArrayBase componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); if (componentsInChildren2 != null && componentsInChildren2.Length > 0) { skin = componentsInChildren2[0]; target = (Renderer)(object)componentsInChildren2[0]; donor = ((Renderer)componentsInChildren2[0]).sharedMaterial; swapName = ((Object)componentsInChildren2[0]).name; return true; } } catch { } detail += " nothing-to-swap"; return false; } private static void NeutralizePropertyBlockHelper(RewardGourd gourd) { //IL_006e: 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) try { PropertyBlockHelper propertyBlockHelper = gourd.propertyBlockHelper; if ((Object)(object)propertyBlockHelper == (Object)null) { return; } try { Il2CppReferenceArray colorSettings = propertyBlockHelper.colorSettings; if (colorSettings != null) { for (int i = 0; i < ((Il2CppArrayBase)(object)colorSettings).Length; i++) { ColorSetting val = ((Il2CppArrayBase)(object)colorSettings)[i]; val.color = Color.white; ((Il2CppArrayBase)(object)colorSettings)[i] = val; } } } catch { } try { propertyBlockHelper.Refresh(); } catch { } ((Behaviour)propertyBlockHelper).enabled = false; Object.Destroy((Object)(object)propertyBlockHelper); } catch { } try { gourd.variantChallengeColor = Color.white; } catch { } } private static void ApplyDingus(Material mat, Texture2D tex) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mat == (Object)null || (Object)(object)tex == (Object)null) { return; } mat.mainTexture = (Texture)(object)tex; for (int i = 0; i < AlbedoProps.Length; i++) { string text = AlbedoProps[i]; try { if (mat.HasProperty(text)) { mat.SetTexture(text, (Texture)(object)tex); mat.SetTextureScale(text, Vector2.one); mat.SetTextureOffset(text, Vector2.zero); } } catch { } } for (int j = 0; j < TintProps.Length; j++) { string text2 = TintProps[j]; try { if (mat.HasProperty(text2)) { mat.SetColor(text2, Color.white); } } catch { } } } private static void Paint(Renderer r, Material[] mats, Texture2D tex) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) ApplyDingus(mats[0], tex); try { if (mats.Length > 1) { r.sharedMaterials = Il2CppReferenceArray.op_Implicit(mats); } else { r.sharedMaterial = mats[0]; } } catch { try { r.sharedMaterial = mats[0]; } catch { } } try { Block.Clear(); for (int i = 0; i < TintProps.Length; i++) { try { Block.SetColor(TintProps[i], Color.white); } catch { } } r.SetPropertyBlock(Block); } catch { try { r.SetPropertyBlock((MaterialPropertyBlock)null); } catch { } } try { r.forceRenderingOff = false; r.enabled = true; r.shadowCastingMode = (ShadowCastingMode)1; r.receiveShadows = true; } catch { } } private static void HideOtherMeshRenderers(Transform root, MeshRenderer keep) { MeshRenderer[] array; try { array = Il2CppArrayBase.op_Implicit(((Component)root).GetComponentsInChildren(true)); } catch { return; } if (array == null) { return; } foreach (MeshRenderer val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)keep)) { try { ((Renderer)val).forceRenderingOff = true; ((Renderer)val).enabled = false; } catch { } } } } public static void ApplyTexture(Material mat, Texture2D tex) { ApplyDingus(mat, tex); } } public sealed class GourdwellController : MonoBehaviour { private const int StateLocked = 0; private const int StateLoose = 1; private static AudioSource _themeSource; private static AudioSource _purrSource; private const float PurrTail = 0.9f; private const float PurrFadeIn = 0.12f; private const float PurrFadeOut = 0.45f; private static Transform _purrFollow; private static float _purrUntil; private Transform _themeFollow; private float _nextVisualScan; private float _nextGourdCache; private float _nextConfigCheck; private DateTime _configStamp; private static string _appliedUpAxis; private static float _appliedSpin = float.NaN; private static float _appliedScale = float.NaN; private float _themeStopAt = -1f; private bool _themeFromRaise; private bool _localWasRaising; private static readonly Dictionary KnownGourds = new Dictionary(); private static readonly HashSet Applied = new HashSet(); private static readonly Dictionary LastState = new Dictionary(); private static readonly Dictionary LockedSince = new Dictionary(); private static readonly HashSet ThemePlayed = new HashSet(); private void Start() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown if (!LoadVisualAssets()) { Plugin.Log.LogError((object)"Maxwell mesh/texture failed to load. Expected assets/maxwell.obj and assets/dingus.jpg."); } else { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(33, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Asset statics ok: mesh="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted((Object)(object)GourdAssets.Mesh != (Object)null); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" mat="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted((Object)(object)GourdAssets.Material != (Object)null); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" tex="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted((Object)(object)GourdAssets.Texture != (Object)null); } log.LogInfo(val); } if (!LoadAudioAsset()) { Plugin.Log.LogError((object)"Maxwell theme failed to load. Expected assets/maxwell.wav."); } if (Plugin.PetHandAnimation.Value) { PetHandAnimator.Install(); } } private void Update() { if (Plugin.Enabled.Value) { EnsureThemeSource(); TickPurr(); PollConfigFile(); RefreshOrientationIfNeeded(); RefreshGourdCacheIfNeeded(); RememberHeldGourds(); WatchGourdOpenings(); WatchRaisedGourd(); WatchPetting(); UpdateThemePosition(); StopThemeIfExpired(); if (GourdAssets.VisualsReady && !(Time.unscaledTime < _nextVisualScan)) { _nextVisualScan = Time.unscaledTime + Mathf.Min(Plugin.ScanInterval.Value, 0.5f); ApplyToAllGourds(); } } } private void LateUpdate() { if (Plugin.Enabled.Value && GourdAssets.VisualsReady) { GourdVisual.MaintainAll(GourdAssets.Texture); GourdPet.Tick(); } } private void WatchPetting() { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown if (!Plugin.PetEnabled.Value) { return; } try { PlayerCharacter val = FindLocalPlayer(); if (!((Object)(object)val == (Object)null) && val.hands != null && val.hands.isHoldingSomething) { RewardGourd val2 = FindRewardGourd(val.hands.heldProp); if (!((Object)(object)val2 == (Object)null) && UsePressed(val) && !IsAimingAtSomething(val)) { Pet(val2); } } } catch (Exception ex) { if (Plugin.LogVerbose.Value) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(18, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Pet watch failed: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(ex.Message); } log.LogWarning(val3); } } } private void Pet(RewardGourd gourd) { //IL_0018: 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) //IL_0057: Expected O, but got Unknown Transform visual = GourdVisual.GetVisual(gourd); if ((Object)(object)visual == (Object)null) { return; } GourdPet.Pet(((Object)gourd).GetInstanceID(), visual, MeshOrientation.Up); if (Plugin.PetHandAnimation.Value) { PetHandAnimator.Begin(visual); } StartPurring(visual); if (Plugin.LogVerbose.Value) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(10, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Petted '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(SafeName(gourd)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("'."); } log.LogInfo(val); } } private static bool UsePressed(PlayerCharacter player) { try { Player inputPlayer = player.inputPlayer; if (inputPlayer != null) { return inputPlayer.GetButtonDown(Action.use); } } catch { } try { return Input.GetMouseButtonDown(0); } catch { return false; } } private static bool IsAimingAtSomething(PlayerCharacter player) { try { PlayerCaster caster = player.caster; if (caster == null) { return false; } if ((Object)(object)caster.castableTarget != (Object)null || (Object)(object)caster.castCharacter != (Object)null) { return true; } Prop castProp = caster.castProp; if ((Object)(object)castProp == (Object)null) { return false; } Prop val = ((player.hands != null) ? player.hands.heldProp : null); return (Object)(object)val == (Object)null || ((Object)castProp).GetInstanceID() != ((Object)val).GetInstanceID(); } catch { return false; } } private void StartPurring(Transform visual) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) EnsurePurrSource(); if ((Object)(object)_purrSource == (Object)null || (Object)(object)GourdAssets.PurrClip == (Object)null) { return; } try { _purrFollow = visual; _purrUntil = Time.unscaledTime + 0.9f; if (!_purrSource.isPlaying) { ((Component)_purrSource).transform.position = visual.position; _purrSource.volume = 0f; _purrSource.time = Random.Range(0f, Mathf.Max(0f, GourdAssets.PurrClip.length - 1f)); _purrSource.Play(); } } catch { } } private void TickPurr() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_purrSource == (Object)null || !_purrSource.isPlaying) { return; } try { if ((Object)(object)_purrFollow != (Object)null) { ((Component)_purrSource).transform.position = _purrFollow.position; } bool num = Time.unscaledTime < _purrUntil; float num2 = (num ? Mathf.Clamp01(Plugin.PetVolume.Value) : 0f); float num3 = (num ? 0.12f : 0.45f); _purrSource.volume = Mathf.MoveTowards(_purrSource.volume, num2, Time.unscaledDeltaTime / num3); if (!num && _purrSource.volume <= 0.001f) { _purrSource.Stop(); _purrFollow = null; } } catch { } } private void EnsurePurrSource() { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown if ((Object)(object)_purrSource != (Object)null) { return; } try { GameObject val = GameObject.Find("Gourdwell_PurrEmitter"); if ((Object)(object)val == (Object)null) { val = new GameObject("Gourdwell_PurrEmitter"); Object.DontDestroyOnLoad((Object)(object)val); } _purrSource = val.GetComponent(); if ((Object)(object)_purrSource == (Object)null) { _purrSource = val.AddComponent(); } _purrSource.playOnAwake = false; _purrSource.loop = true; _purrSource.clip = GourdAssets.PurrClip; _purrSource.volume = 0f; _purrSource.spatialBlend = 1f; _purrSource.rolloffMode = (AudioRolloffMode)1; _purrSource.dopplerLevel = 0f; _purrSource.bypassReverbZones = true; _purrSource.minDistance = 1.5f; _purrSource.maxDistance = 12f; } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(26, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Purr source setup failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } log.LogWarning(val2); } } private void EnsureThemeSource() { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown if ((Object)(object)_themeSource != (Object)null || !GourdAssets.AudioReady) { return; } try { GameObject val = GameObject.Find("Gourdwell_ThemeEmitter"); if ((Object)(object)val == (Object)null) { val = new GameObject("Gourdwell_ThemeEmitter"); Object.DontDestroyOnLoad((Object)(object)val); } _themeSource = val.GetComponent(); if ((Object)(object)_themeSource == (Object)null) { _themeSource = val.AddComponent(); } _themeSource.playOnAwake = false; _themeSource.loop = false; _themeSource.clip = GourdAssets.ThemeClip; ConfigureSpatialTheme(_themeSource); } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(28, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Theme source rebind failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } log.LogWarning(val2); } } private void RefreshGourdCacheIfNeeded() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Expected O, but got Unknown if (Time.unscaledTime < _nextGourdCache) { return; } _nextGourdCache = Time.unscaledTime + Mathf.Min(Plugin.ScanInterval.Value, 0.5f); int count = KnownGourds.Count; bool flag = default(bool); try { Il2CppArrayBase val = Object.FindObjectsOfType(true); if (val != null) { for (int i = 0; i < val.Length; i++) { Remember(val[i]); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(25, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("RewardGourd scan failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } log.LogWarning(val2); } try { Il2CppArrayBase val3 = Object.FindObjectsOfType(true); if (val3 != null) { for (int j = 0; j < val3.Length; j++) { Prop val4 = val3[j]; if (!((Object)(object)val4 == (Object)null)) { bool flag2 = false; try { flag2 = val4.MatchesGroup((PropGroup)19); } catch { } if (flag2) { Remember(FindRewardGourd(val4)); } } } } } catch (Exception ex2) { ManualLogSource log2 = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(30, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Prop/RewardGourd scan failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex2.Message); } log2.LogWarning(val2); } PruneKnownGourds(); if (Plugin.LogVerbose.Value && (KnownGourds.Count != count || KnownGourds.Count == 0)) { ManualLogSource log3 = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(34, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("Gourd cache: "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted(KnownGourds.Count); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" known. visualsReady="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted(GourdAssets.VisualsReady); } log3.LogInfo(val5); } } private void RememberHeldGourds() { try { List allPlayerCharacters = PlayerCharacter.allPlayerCharacters; if (allPlayerCharacters == null) { return; } for (int i = 0; i < allPlayerCharacters.Count; i++) { PlayerCharacter val = allPlayerCharacters[i]; if (!((Object)(object)val == (Object)null) && val.hands != null && val.hands.isHoldingSomething) { Remember(FindRewardGourd(val.hands.heldProp)); } } } catch { } } private void Remember(RewardGourd gourd) { if ((Object)(object)gourd == (Object)null) { return; } try { int instanceID = ((Object)gourd).GetInstanceID(); bool num = !KnownGourds.ContainsKey(instanceID); KnownGourds[instanceID] = gourd; if (num && GourdAssets.VisualsReady) { TryApplyOne(gourd, force: false); } } catch { } } private static void PruneKnownGourds() { List list = null; foreach (KeyValuePair knownGourd in KnownGourds) { if ((Object)(object)knownGourd.Value == (Object)null) { if (list == null) { list = new List(); } list.Add(knownGourd.Key); } } if (list != null) { for (int i = 0; i < list.Count; i++) { KnownGourds.Remove(list[i]); Applied.Remove(list[i]); } } } private bool LoadVisualAssets() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown if (GourdAssets.VisualsReady) { return true; } string path = Path.Combine(ObjLoader.PluginDir(), "assets"); string text = Path.Combine(path, "maxwell.obj"); string text2 = Path.Combine(path, "dingus.jpg"); string text3 = Path.Combine(path, "dingus_whiskers.png"); bool flag = default(bool); if (!ObjLoader.TryLoad(text, out var mesh, out var materialNames)) { ManualLogSource log = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(20, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not load OBJ: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(text); } log.LogError(val); return false; } ((Object)mesh).hideFlags = (HideFlags)61; GourdAssets.Mesh = mesh; CacheBaseGeometry(mesh); ApplyOrientation(); if (!ObjLoader.TryLoadTexture(text2, out var tex)) { ManualLogSource log2 = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(24, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not load texture: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(text2); } log2.LogError(val); return false; } ((Object)tex).hideFlags = (HideFlags)61; GourdAssets.Texture = tex; Material val2 = CreateMaterial(tex); if ((Object)(object)val2 == (Object)null) { return false; } ((Object)val2).hideFlags = (HideFlags)61; GourdAssets.Material = val2; if (ObjLoader.TryLoadTexture(text3, out var tex2)) { ((Object)tex2).hideFlags = (HideFlags)61; GourdAssets.WhiskerTexture = tex2; } else { ManualLogSource log3 = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(53, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("No whisker texture at "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(text3); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("; whisker cards will be hidden."); } log3.LogWarning(val3); } Material val4 = CreateWhiskerMaterial(GourdAssets.WhiskerTexture); if ((Object)(object)val4 != (Object)null) { ((Object)val4).hideFlags = (HideFlags)61; GourdAssets.WhiskerMaterial = val4; } GourdAssets.SubMeshMaterials = BuildSubMeshMaterials(materialNames, val2, val4); ManualLogSource log4 = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(61, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("Maxwell visuals ready (verts="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted(mesh.vertexCount); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(", tris="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted(((Il2CppArrayBase)(object)mesh.triangles).Length / 3); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("submeshes="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted(mesh.subMeshCount); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(", groups=["); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted(string.Join(", ", materialNames)); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("])."); } log4.LogInfo(val5); return true; } private static Material[] BuildSubMeshMaterials(string[] names, Material body, Material whiskers) { if (names == null || names.Length == 0) { return (Material[])(object)new Material[1] { body }; } Material[] array = (Material[])(object)new Material[names.Length]; for (int i = 0; i < names.Length; i++) { bool flag = names[i] != null && names[i].IndexOf("whisk", StringComparison.OrdinalIgnoreCase) >= 0; array[i] = ((flag && (Object)(object)whiskers != (Object)null) ? whiskers : body); } return array; } private static void CacheBaseGeometry(Mesh mesh) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) Il2CppStructArray vertices = mesh.vertices; Vector3[] array = (Vector3[])(object)new Vector3[((Il2CppArrayBase)(object)vertices).Length]; for (int i = 0; i < ((Il2CppArrayBase)(object)vertices).Length; i++) { array[i] = ((Il2CppArrayBase)(object)vertices)[i]; } GourdAssets.BaseVertices = array; Il2CppStructArray normals = mesh.normals; if (normals != null && ((Il2CppArrayBase)(object)normals).Length == ((Il2CppArrayBase)(object)vertices).Length) { Vector3[] array2 = (Vector3[])(object)new Vector3[((Il2CppArrayBase)(object)normals).Length]; for (int j = 0; j < ((Il2CppArrayBase)(object)normals).Length; j++) { array2[j] = ((Il2CppArrayBase)(object)normals)[j]; } GourdAssets.BaseNormals = array2; } } private static void ApplyOrientation() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_0118: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Expected O, but got Unknown //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: 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) Mesh mesh = GourdAssets.Mesh; Vector3[] baseVertices = GourdAssets.BaseVertices; if ((Object)(object)mesh == (Object)null || baseVertices == null || baseVertices.Length == 0) { return; } Quaternion val = MeshOrientation.Rotation(); Vector3[] array = (Vector3[])(object)new Vector3[baseVertices.Length]; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(float.MaxValue, float.MaxValue, float.MaxValue); Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(float.MinValue, float.MinValue, float.MinValue); for (int i = 0; i < baseVertices.Length; i++) { Vector3 val4 = (array[i] = val * baseVertices[i]); val2 = Vector3.Min(val2, val4); val3 = Vector3.Max(val3, val4); } Vector3 val5 = (val2 + val3) * 0.5f; Vector3 val6 = val3 - val2; float num = Mathf.Max(val6.x, Mathf.Max(val6.y, val6.z)); if (num < 1E-05f) { num = 1f; } float num2 = Plugin.ScaleMultiplier.Value / num; for (int j = 0; j < array.Length; j++) { array[j] = (array[j] - val5) * num2; } mesh.SetVertices(Il2CppStructArray.op_Implicit(array)); Vector3[] baseNormals = GourdAssets.BaseNormals; if (baseNormals != null && baseNormals.Length == baseVertices.Length) { Vector3[] array2 = (Vector3[])(object)new Vector3[baseNormals.Length]; for (int k = 0; k < baseNormals.Length; k++) { array2[k] = val * baseNormals[k]; } mesh.SetNormals(Il2CppStructArray.op_Implicit(array2)); } mesh.RecalculateBounds(); mesh.RecalculateTangents(); BackProfile.Build(array, MeshOrientation.Forward, MeshOrientation.Up); _appliedUpAxis = Plugin.UpAxis.Value; _appliedSpin = Plugin.Spin.Value; _appliedScale = Plugin.ScaleMultiplier.Value; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val7 = new BepInExInfoLogInterpolatedStringHandler(39, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("Maxwell orientation: up="); ((BepInExLogInterpolatedStringHandler)val7).AppendFormatted(_appliedUpAxis); ((BepInExLogInterpolatedStringHandler)val7).AppendLiteral(" spin="); ((BepInExLogInterpolatedStringHandler)val7).AppendFormatted(_appliedSpin, "0.#"); ((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("° scale="); ((BepInExLogInterpolatedStringHandler)val7).AppendFormatted(_appliedScale, "0.##"); ((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("."); } log.LogInfo(val7); } private void RefreshOrientationIfNeeded() { if (!((Object)(object)GourdAssets.Mesh == (Object)null) && (!(_appliedUpAxis == Plugin.UpAxis.Value) || !Mathf.Approximately(_appliedSpin, Plugin.Spin.Value) || !Mathf.Approximately(_appliedScale, Plugin.ScaleMultiplier.Value))) { ApplyOrientation(); } } private void PollConfigFile() { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown if (Time.unscaledTime < _nextConfigCheck) { return; } _nextConfigCheck = Time.unscaledTime + 1f; try { string configFilePath = ((BasePlugin)Plugin.Instance).Config.ConfigFilePath; if (!File.Exists(configFilePath)) { return; } DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(configFilePath); if (!(lastWriteTimeUtc == _configStamp)) { bool num = _configStamp == default(DateTime); _configStamp = lastWriteTimeUtc; if (!num) { ((BasePlugin)Plugin.Instance).Config.Reload(); } } } catch (Exception ex) { if (Plugin.LogVerbose.Value) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(28, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Config reload check failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } log.LogWarning(val); } } } private bool LoadAudioAsset() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Expected O, but got Unknown bool flag = default(bool); if ((Object)(object)GourdAssets.PurrClip == (Object)null) { try { if (WavLoader.TryLoad(Path.Combine(ObjLoader.PluginDir(), "assets", "purr.wav"), out var clip)) { ((Object)clip).hideFlags = (HideFlags)61; GourdAssets.PurrClip = clip; } else { Plugin.Log.LogWarning((object)"assets/purr.wav missing; falling back to the synthesised purr."); AudioClip obj = PurrSynth.Create(); ((Object)obj).hideFlags = (HideFlags)61; GourdAssets.PurrClip = obj; } } catch (Exception ex) { ManualLogSource log = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(42, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Purr load failed, petting will be silent: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } log.LogWarning(val); } } if ((Object)(object)GourdAssets.ThemeClip == (Object)null) { string path = Path.Combine(ObjLoader.PluginDir(), "assets", "maxwell.wav"); float value = Plugin.ThemeMaxSeconds.Value; if (!WavLoader.TryLoad(path, out var clip2, value)) { return false; } ((Object)clip2).hideFlags = (HideFlags)61; GourdAssets.ThemeClip = clip2; } GameObject val2 = new GameObject("Gourdwell_ThemeEmitter"); Object.DontDestroyOnLoad((Object)val2); _themeSource = val2.AddComponent(); _themeSource.playOnAwake = false; _themeSource.loop = false; _themeSource.clip = GourdAssets.ThemeClip; ConfigureSpatialTheme(_themeSource); ManualLogSource log2 = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(41, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Maxwell theme ready ("); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(GourdAssets.ThemeClip.length, "F1"); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("s, cap="); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(Plugin.ThemeMaxSeconds.Value, "F1"); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("s, 3D local)."); } log2.LogInfo(val3); return true; } private static void ConfigureSpatialTheme(AudioSource src) { src.spatialBlend = 1f; src.rolloffMode = (AudioRolloffMode)1; src.dopplerLevel = 0f; src.spread = 0f; src.bypassReverbZones = true; src.minDistance = Mathf.Max(0.5f, Plugin.ThemeMinDistance.Value); src.maxDistance = Mathf.Max(src.minDistance + 0.5f, Plugin.ThemeMaxDistance.Value); } private void WatchGourdOpenings() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected I4, but got Unknown if (!Plugin.PlayThemeOnOpen.Value || (Object)(object)_themeSource == (Object)null || !GourdAssets.AudioReady) { return; } float value = Plugin.MinLockedSeconds.Value; foreach (KeyValuePair knownGourd in KnownGourds) { RewardGourd value2 = knownGourd.Value; if ((Object)(object)value2 == (Object)null) { continue; } int num; try { num = (int)value2.gourdState; } catch { continue; } int key = knownGourd.Key; if (!LastState.TryGetValue(key, out var value3)) { LastState[key] = num; if (num == 0) { LockedSince[key] = Time.unscaledTime; } continue; } if (num == 0 && !LockedSince.ContainsKey(key)) { LockedSince[key] = Time.unscaledTime; } if (value3 == 0 && num == 1 && !ThemePlayed.Contains(key)) { if (LockedSince.TryGetValue(key, out var value4) && Time.unscaledTime - value4 >= value) { PlayTheme(value2, "released from vice (Locked → Loose)", fromRaise: false); ThemePlayed.Add(key); } LockedSince.Remove(key); } if (num != 0) { LockedSince.Remove(key); } LastState[key] = num; } } private void WatchRaisedGourd() { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown bool flag = false; RewardGourd val = null; try { PlayerCharacter val2 = FindLocalPlayer(); if ((Object)(object)val2 != (Object)null && val2.gestures != null && val2.gestures.isHoldingRaised && val2.hands != null && val2.hands.isHoldingSomething) { val = FindRewardGourd(val2.hands.heldProp); flag = (Object)(object)val != (Object)null; if (flag) { Remember(val); } } } catch (Exception ex) { if (Plugin.LogVerbose.Value) { ManualLogSource log = Plugin.Log; bool flag2 = default(bool); BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(20, 1, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Raise watch failed: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(ex.Message); } log.LogWarning(val3); } } if (flag && !_localWasRaising) { if (Plugin.PlayThemeOnRaise.Value && (Object)(object)_themeSource != (Object)null && GourdAssets.AudioReady) { PlayTheme(val, "held over head", fromRaise: true); } TryApplyOne(val, force: false); } else if (!flag && _localWasRaising && _themeFromRaise) { StopTheme("lowered gourd"); } _localWasRaising = flag; } private void UpdateThemePosition() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_themeSource == (Object)null) && _themeSource.isPlaying && !((Object)(object)_themeFollow == (Object)null)) { ((Component)_themeSource).transform.position = _themeFollow.position; } } private void StopThemeIfExpired() { if (!(_themeStopAt < 0f) && !((Object)(object)_themeSource == (Object)null) && !(Time.unscaledTime < _themeStopAt)) { StopTheme("max duration"); } } private void StopTheme(string reason) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown _themeStopAt = -1f; _themeFollow = null; _themeFromRaise = false; if (!((Object)(object)_themeSource != (Object)null) || !_themeSource.isPlaying) { return; } _themeSource.Stop(); if (Plugin.LogVerbose.Value) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(25, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Stopped Maxwell theme ("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(reason); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")."); } log.LogInfo(val); } } private void PlayTheme(RewardGourd gourd, string reason, bool fromRaise) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown if ((Object)(object)gourd == (Object)null || (Object)(object)_themeSource == (Object)null) { return; } ConfigureSpatialTheme(_themeSource); Vector3 position = ((Component)gourd).transform.position; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val; if (!IsLocalListenerInRange(position)) { if (Plugin.LogVerbose.Value) { ManualLogSource log = Plugin.Log; val = new BepInExInfoLogInterpolatedStringHandler(48, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Skip theme for '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(SafeName(gourd)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' — outside local hearing range."); } log.LogInfo(val); } return; } _themeFollow = ((Component)gourd).transform; _themeFromRaise = fromRaise; ((Component)_themeSource).transform.position = position; _themeSource.volume = Mathf.Clamp01(Plugin.ThemeVolume.Value); if (_themeSource.isPlaying) { _themeSource.Stop(); } _themeSource.Play(); _themeStopAt = Time.unscaledTime + Mathf.Max(0.1f, Plugin.ThemeMaxSeconds.Value); ManualLogSource log2 = Plugin.Log; val = new BepInExInfoLogInterpolatedStringHandler(39, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Playing Maxwell theme (local 3D) — '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(SafeName(gourd)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(reason); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } log2.LogInfo(val); } private static bool IsLocalListenerInRange(Vector3 origin) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_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) float num = Mathf.Max(1f, Plugin.ThemeMaxDistance.Value); Vector3? localListenerPosition = GetLocalListenerPosition(); if (!localListenerPosition.HasValue) { return true; } Vector3 val = localListenerPosition.Value - origin; return ((Vector3)(ref val)).sqrMagnitude <= num * num; } private static Vector3? GetLocalListenerPosition() { //IL_0015: 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) try { PlayerCharacter val = FindLocalPlayer(); if ((Object)(object)val != (Object)null) { return ((Component)val).transform.position; } } catch { } try { Camera main = Camera.main; if ((Object)(object)main != (Object)null) { return ((Component)main).transform.position; } } catch { } return null; } private static PlayerCharacter FindLocalPlayer() { try { List allPlayerCharacters = PlayerCharacter.allPlayerCharacters; if (allPlayerCharacters == null) { return null; } for (int i = 0; i < allPlayerCharacters.Count; i++) { PlayerCharacter val = allPlayerCharacters[i]; if ((Object)(object)val != (Object)null && ((NetworkBehaviour)val).isLocalPlayer) { return val; } } } catch { } return null; } private static RewardGourd FindRewardGourd(Prop prop) { if ((Object)(object)prop == (Object)null) { return null; } try { RewardGourd component = ((Component)prop).GetComponent(); if ((Object)(object)component != (Object)null) { return component; } RewardGourd componentInParent = ((Component)prop).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { return componentInParent; } return ((Component)prop).GetComponentInChildren(true); } catch { return null; } } private static Material CreateMaterial(Texture2D tex) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00b8: Expected O, but got Unknown string[] array = new string[3] { "Universal Render Pipeline/Lit", "Universal Render Pipeline/Simple Lit", "Universal Render Pipeline/Unlit" }; Shader val = null; string text = null; for (int i = 0; i < array.Length; i++) { val = Shader.Find(array[i]); if ((Object)(object)val != (Object)null) { text = array[i]; break; } } if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"No usable shader found for Gourdwell material."); return null; } Material val2 = new Material(val) { name = "Gourdwell_Mat" }; GourdVisual.ApplyTexture(val2, tex); ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(29, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Gourdwell material shader='"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(text); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("'."); } log.LogInfo(val3); return val2; } private static Material CreateWhiskerMaterial(Texture2D tex) { //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) string[] array = new string[3] { "Universal Render Pipeline/Lit", "Universal Render Pipeline/Simple Lit", "Universal Render Pipeline/Unlit" }; Shader val = null; for (int i = 0; i < array.Length; i++) { val = Shader.Find(array[i]); if ((Object)(object)val != (Object)null) { break; } } if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"No shader available for whisker material."); return null; } if ((Object)(object)tex == (Object)null) { tex = new Texture2D(1, 1, (TextureFormat)4, false) { hideFlags = (HideFlags)61 }; tex.SetPixel(0, 0, new Color(1f, 1f, 1f, 0f)); tex.Apply(false, false); } Material val2 = new Material(val) { name = "Gourdwell_Whiskers" }; val2.mainTexture = (Texture)(object)tex; try { if (val2.HasProperty("_BaseMap")) { val2.SetTexture("_BaseMap", (Texture)(object)tex); } if (val2.HasProperty("_MainTex")) { val2.SetTexture("_MainTex", (Texture)(object)tex); } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", Color.white); } if (val2.HasProperty("_Color")) { val2.SetColor("_Color", Color.white); } if (val2.HasProperty("_Surface")) { val2.SetFloat("_Surface", 1f); } if (val2.HasProperty("_Blend")) { val2.SetFloat("_Blend", 0f); } if (val2.HasProperty("_AlphaClip")) { val2.SetFloat("_AlphaClip", 0f); } if (val2.HasProperty("_ZWrite")) { val2.SetFloat("_ZWrite", 0f); } if (val2.HasProperty("_Cull")) { val2.SetFloat("_Cull", 0f); } if (val2.HasProperty("_Metallic")) { val2.SetFloat("_Metallic", 0f); } if (val2.HasProperty("_Smoothness")) { val2.SetFloat("_Smoothness", 0f); } if (val2.HasProperty("_SrcBlend")) { val2.SetFloat("_SrcBlend", 5f); } if (val2.HasProperty("_DstBlend")) { val2.SetFloat("_DstBlend", 10f); } val2.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); val2.DisableKeyword("_ALPHATEST_ON"); val2.SetOverrideTag("RenderType", "Transparent"); val2.renderQueue = 3000; } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(41, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Whisker material setup partially failed: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(ex.Message); } log.LogWarning(val3); } return val2; } private void ApplyToAllGourds() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown if (KnownGourds.Count == 0) { if (Plugin.LogVerbose.Value) { Plugin.Log.LogInfo((object)"Apply scan: no RewardGourd instances known yet."); } return; } if (Plugin.LogVerbose.Value) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(30, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Apply scan: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(KnownGourds.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" gourds, applied="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(Applied.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("."); } log.LogInfo(val); } foreach (KeyValuePair knownGourd in KnownGourds) { TryApplyOne(knownGourd.Value, force: false); } } private void TryApplyOne(RewardGourd gourd, bool force) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown if ((Object)(object)gourd == (Object)null) { return; } bool flag = default(bool); if (!GourdAssets.VisualsReady) { ManualLogSource log = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(45, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("TryApplyOne: assets not ready mesh="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted((Object)(object)GourdAssets.Mesh != (Object)null); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" mat="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted((Object)(object)GourdAssets.Material != (Object)null); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" tex="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted((Object)(object)GourdAssets.Texture != (Object)null); } log.LogWarning(val); return; } int instanceID; try { instanceID = ((Object)gourd).GetInstanceID(); } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(35, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("TryApplyOne: GetInstanceID failed: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } log2.LogWarning(val); return; } if (!force && Applied.Contains(instanceID)) { return; } try { if (GourdVisual.SwapInPlace(gourd, GourdAssets.Mesh, GourdAssets.Material, GourdAssets.Texture, GourdAssets.WhiskerMaterial, out var detail) > 0) { Applied.Add(instanceID); ManualLogSource log3 = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(33, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Applied Gourdwell visual to '"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(SafeName(gourd)); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' ("); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(detail); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(")"); } log3.LogInfo(val2); } else { ManualLogSource log4 = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(38, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Gourdwell: swap found nothing on '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(SafeName(gourd)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' ("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(detail); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")"); } log4.LogWarning(val); } } catch (Exception ex2) { ManualLogSource log5 = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(25, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("TryApplyOne threw on '"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(SafeName(gourd)); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("': "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(ex2); } log5.LogError(val3); } } private static string SafeName(RewardGourd gourd) { try { return ((Object)(object)gourd != (Object)null) ? ((Object)gourd).name : "(null)"; } catch { return "(gourd)"; } } } internal static class MeshOrientation { private static readonly Vector3 ModelForward = new Vector3(-1f, 0f, 0f); public static Vector3 Up => ParseAxis(Plugin.UpAxis.Value); public static Vector3 Forward => Rotation() * ModelForward; public static Vector3 ParseAxis(string value) { //IL_0058: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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) return (Vector3)((value ?? "+Y").Trim().ToUpperInvariant() switch { "+X" => Vector3.right, "-X" => Vector3.left, "-Y" => Vector3.down, "+Z" => Vector3.forward, "-Z" => Vector3.back, _ => Vector3.up, }); } public static Quaternion Rotation() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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) Vector3 up = Up; return Quaternion.AngleAxis(Plugin.Spin.Value, up) * Quaternion.FromToRotation(Vector3.up, up); } } internal static class ObjLoader { public static bool TryLoad(string objPath, out Mesh mesh, out string[] materialNames) { //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: 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_02b5: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) mesh = null; materialNames = new string[0]; if (!File.Exists(objPath)) { return false; } List positions = new List(); List uvs = new List(); List normals = new List(); List outPos = new List(); List outUv = new List(); List outNorm = new List(); Dictionary map = new Dictionary(); List groupNames = new List(); List> groupIndices = new List>(); List indices = null; foreach (string item4 in File.ReadLines(objPath)) { string text = item4.Trim(); if (text.Length == 0 || text[0] == '#') { continue; } string[] array = text.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0) { continue; } switch (array[0]) { case "v": if (array.Length >= 4) { positions.Add(new Vector3(0f - F(array[1]), F(array[2]), F(array[3]))); } break; case "vt": if (array.Length >= 3) { uvs.Add(new Vector2(F(array[1]), F(array[2]))); } break; case "vn": if (array.Length >= 4) { normals.Add(new Vector3(0f - F(array[1]), F(array[2]), F(array[3]))); } break; case "usemtl": if (array.Length >= 2) { StartGroup(array[1]); } break; case "f": if (array.Length >= 4) { if (indices == null) { StartGroup("default"); } for (int i = 1; i + 2 < array.Length; i++) { AddVert(array[1]); AddVert(array[i + 2]); AddVert(array[i + 1]); } } break; } } for (int num = groupIndices.Count - 1; num >= 0; num--) { if (groupIndices[num].Count == 0) { groupIndices.RemoveAt(num); groupNames.RemoveAt(num); } } if (outPos.Count == 0 || groupIndices.Count == 0) { return false; } mesh = new Mesh { name = Path.GetFileNameWithoutExtension(objPath) }; mesh.SetVertices(Il2CppStructArray.op_Implicit(outPos.ToArray())); if (outUv.Count == outPos.Count) { mesh.SetUVs(0, Il2CppStructArray.op_Implicit(outUv.ToArray())); } if (outNorm.Count == outPos.Count) { mesh.SetNormals(Il2CppStructArray.op_Implicit(outNorm.ToArray())); } mesh.subMeshCount = groupIndices.Count; for (int j = 0; j < groupIndices.Count; j++) { mesh.SetTriangles(Il2CppStructArray.op_Implicit(groupIndices[j].ToArray()), j); } if (outNorm.Count != outPos.Count) { mesh.RecalculateNormals(); } mesh.RecalculateBounds(); materialNames = groupNames.ToArray(); return true; void AddVert(string token) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_0126: 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_013f: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) if (!map.TryGetValue(token, out var value)) { string[] array2 = token.Split('/'); int num2 = int.Parse(array2[0], CultureInfo.InvariantCulture); if (num2 < 0) { num2 = positions.Count + num2 + 1; } Vector3 item = positions[num2 - 1]; Vector2 item2 = Vector2.zero; if (array2.Length > 1 && array2[1].Length > 0) { int num3 = int.Parse(array2[1], CultureInfo.InvariantCulture); if (num3 < 0) { num3 = uvs.Count + num3 + 1; } if (num3 > 0 && num3 <= uvs.Count) { item2 = uvs[num3 - 1]; } } Vector3 item3 = Vector3.up; if (array2.Length > 2 && array2[2].Length > 0) { int num4 = int.Parse(array2[2], CultureInfo.InvariantCulture); if (num4 < 0) { num4 = normals.Count + num4 + 1; } if (num4 > 0 && num4 <= normals.Count) { item3 = normals[num4 - 1]; } } value = outPos.Count; outPos.Add(item); outUv.Add(item2); outNorm.Add(item3); map[token] = value; } indices.Add(value); } void StartGroup(string name) { int num2 = groupNames.IndexOf(name); if (num2 >= 0) { indices = groupIndices[num2]; } else { indices = new List(); groupNames.Add(name); groupIndices.Add(indices); } } } public static bool TryLoadTexture(string path, out Texture2D tex) { //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown tex = null; if (!File.Exists(path)) { return false; } bool flag = default(bool); try { ImageResult val = ImageResult.FromMemory(File.ReadAllBytes(path), (ColorComponents)4); if (val == null || val.Data == null || val.Width <= 0 || val.Height <= 0) { return false; } int width = val.Width; int height = val.Height; byte[] data = val.Data; byte[] array = new byte[width * height * 4]; for (int i = 0; i < height; i++) { int srcOffset = i * width * 4; int dstOffset = (height - 1 - i) * width * 4; Buffer.BlockCopy(data, srcOffset, array, dstOffset, width * 4); } tex = new Texture2D(width, height, (TextureFormat)4, false); tex.LoadRawTextureData(Il2CppStructArray.op_Implicit(array)); tex.Apply(false, false); ((Object)tex).name = Path.GetFileNameWithoutExtension(path); ((Texture)tex).wrapMode = (TextureWrapMode)0; ((Texture)tex).filterMode = (FilterMode)1; ((Texture)tex).anisoLevel = 4; ManualLogSource log = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(18, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Loaded texture "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(((Object)tex).name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(width); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("x"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(height); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } log.LogInfo(val2); return true; } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(24, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Texture load failed ("); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(path); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("): "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(ex); } log2.LogError(val3); if ((Object)(object)tex != (Object)null) { Object.Destroy((Object)(object)tex); tex = null; } return false; } } public static string PluginDir() { return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } private static float F(string s) { return float.Parse(s, CultureInfo.InvariantCulture); } } internal static class PetHandAnimator { private static bool _patched; private static bool _active; private static float _startedAt; private static Transform _visual; private static Vector3 _localUp; private static Vector3 _localForward; private const float Clearance = 0.05f; public static void Install() { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (_patched) { return; } try { MethodInfo methodInfo = AccessTools.Method(typeof(PlayerArms), "LateUpdate", (Type[])null, (Type[])null); if (methodInfo == null) { Plugin.Log.LogWarning((object)"PlayerArms.LateUpdate not found; pet hand animation disabled."); return; } HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(PetHandAnimator), "AfterArmsLateUpdate", (Type[])null, (Type[])null)); new Harmony("BigWalk.Gourdwell").Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _patched = true; Plugin.Log.LogInfo((object)"Pet hand animation hooked into PlayerArms.LateUpdate."); } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(67, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Could not hook PlayerArms.LateUpdate; pet hand animation disabled: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } log.LogWarning(val2); } } public static void Begin(Transform visual) { //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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (_patched && !((Object)(object)visual == (Object)null) && BackProfile.Ready) { _visual = visual; _localUp = MeshOrientation.Up; _localForward = MeshOrientation.Forward; _startedAt = Time.unscaledTime; _active = true; } } private static void AfterArmsLateUpdate(PlayerArms __instance) { //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown //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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_00b8: Unknown result type (might be due to invalid IL or missing references) if (!_active) { return; } try { if (__instance == null || (Object)(object)_visual == (Object)null) { _active = false; return; } PlayerCharacter playerCharacter = __instance.playerCharacter; if ((Object)(object)playerCharacter == (Object)null || !((NetworkBehaviour)playerCharacter).isLocalPlayer) { return; } float num = (Time.unscaledTime - _startedAt) / 0.5f; if (num >= 1f) { _active = false; return; } float blend = Mathf.Sin((float)Math.PI * Mathf.Clamp01(num)); Vector3 target = StrokePoint(num); if (!string.Equals(Plugin.PetHand.Value, "Left", StringComparison.OrdinalIgnoreCase)) { Move(__instance.localRightHand, __instance.localRightArmSpline, target, blend); Move(__instance.rightHand, __instance.rightArmLimbSpline, target, blend); } else { Move(__instance.localLeftHand, __instance.localLeftArmSpline, target, blend); Move(__instance.leftHand, __instance.leftArmLimbSpline, target, blend); } } catch (Exception ex) { _active = false; if (Plugin.LogVerbose.Value) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(28, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Pet hand animation stopped: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(ex.Message); } log.LogWarning(val); } } } private static void Move(Transform hand, LimbSpline spline, Vector3 target, float blend) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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) if (!((Object)(object)hand == (Object)null)) { hand.position = Vector3.Lerp(hand.position, target, blend); if ((Object)(object)spline != (Object)null) { spline.Refresh(); } } } private static Vector3 StrokePoint(float progress) { //IL_001d: 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_0028: 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_003e: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Lerp(BackProfile.Max * 0.75f, BackProfile.Min * 0.85f, progress); Vector3 val = _localForward * num + _localUp * (BackProfile.HeightAt(num) + 0.05f); return _visual.TransformPoint(val); } } [BepInPlugin("BigWalk.Gourdwell", "Gourdwell", "1.0.16")] [BepInProcess("Big Walk.exe")] public class Plugin : BasePlugin { internal static Plugin Instance; internal static ManualLogSource Log; public static ConfigEntry Enabled; public static ConfigEntry ScaleMultiplier; public static ConfigEntry ScanInterval; public static ConfigEntry UpAxis; public static ConfigEntry Spin; public static ConfigEntry PetEnabled; public static ConfigEntry PetVolume; public static ConfigEntry PetHandAnimation; public static ConfigEntry PetHand; public static ConfigEntry PlayThemeOnOpen; public static ConfigEntry PlayThemeOnRaise; public static ConfigEntry ThemeVolume; public static ConfigEntry ThemeMaxSeconds; public static ConfigEntry ThemeMinDistance; public static ConfigEntry ThemeMaxDistance; public static ConfigEntry MinLockedSeconds; public static ConfigEntry LogVerbose; public override void Load() { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected O, but got Unknown //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Expected O, but got Unknown //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Expected O, but got Unknown //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Expected O, but got Unknown //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Expected O, but got Unknown //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Expected O, but got Unknown //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Expected O, but got Unknown //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Expected O, but got Unknown //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_03bf: Expected O, but got Unknown Instance = this; Log = ((BasePlugin)this).Log; Enabled = ((BasePlugin)this).Config.Bind("Gourdwell", "Enabled", true, "Replace Reward Gourd visuals with Maxwell the cat."); ScaleMultiplier = ((BasePlugin)this).Config.Bind("Gourdwell", "ScaleMultiplier", 1.15f, new ConfigDescription("Size relative to the original gourd bounds.", (AcceptableValueBase)(object)new AcceptableValueRange(0.3f, 3f), Array.Empty())); ScanInterval = ((BasePlugin)this).Config.Bind("Gourdwell", "ScanInterval", 0.5f, new ConfigDescription("How often to look for new gourds (seconds).", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 5f), Array.Empty())); UpAxis = ((BasePlugin)this).Config.Bind("Orientation", "UpAxis", "+Z", new ConfigDescription("Which axis of the gourd prop points up in the world. Change this until Maxwell stands upright; if he is upside down, use the opposite sign.", (AcceptableValueBase)(object)new AcceptableValueList(new string[6] { "+X", "-X", "+Y", "-Y", "+Z", "-Z" }), Array.Empty())); Spin = ((BasePlugin)this).Config.Bind("Orientation", "Spin", -180f, new ConfigDescription("Degrees to turn Maxwell around UpAxis. Once he is upright, adjust this (try steps of 90) until he faces whoever is holding the gourd.", (AcceptableValueBase)(object)new AcceptableValueRange(-180f, 180f), Array.Empty())); PetEnabled = ((BasePlugin)this).Config.Bind("Petting", "PetEnabled", true, "Left-click while holding Maxwell (and not aiming at anything interactable) to pet him."); PetVolume = ((BasePlugin)this).Config.Bind("Petting", "PetVolume", 0.7f, new ConfigDescription("Purr volume.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); PetHandAnimation = ((BasePlugin)this).Config.Bind("Petting", "PetHandAnimation", true, "Stroke your hand along Maxwell's back when petting. Turn off if it fights the arm animation."); PetHand = ((BasePlugin)this).Config.Bind("Petting", "PetHand", "Right", new ConfigDescription("Which hand does the petting.", (AcceptableValueBase)(object)new AcceptableValueList(new string[2] { "Left", "Right" }), Array.Empty())); PlayThemeOnOpen = ((BasePlugin)this).Config.Bind("Audio", "PlayThemeOnOpen", true, "Play the Maxwell theme when a gourd is released from a vice (Locked → Loose)."); PlayThemeOnRaise = ((BasePlugin)this).Config.Bind("Audio", "PlayThemeOnRaise", true, "Play the Maxwell theme when the local player holds a Reward Gourd over their head."); ThemeVolume = ((BasePlugin)this).Config.Bind("Audio", "ThemeVolume", 0.68f, new ConfigDescription("Theme volume.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); ThemeMaxSeconds = ((BasePlugin)this).Config.Bind("Audio", "ThemeMaxSeconds", 10f, new ConfigDescription("How long the theme plays before stopping.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 60f), Array.Empty())); ThemeMinDistance = ((BasePlugin)this).Config.Bind("Audio", "ThemeMinDistance", 3f, new ConfigDescription("Full-volume radius for the theme (3D / local only — not lobby-wide).", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 30f), Array.Empty())); ThemeMaxDistance = ((BasePlugin)this).Config.Bind("Audio", "ThemeMaxDistance", 18f, new ConfigDescription("Theme is silent beyond this distance from the gourd. Other clients only hear it if they are nearby.", (AcceptableValueBase)(object)new AcceptableValueRange(5f, 80f), Array.Empty())); MinLockedSeconds = ((BasePlugin)this).Config.Bind("Audio", "MinLockedSeconds", 1.5f, new ConfigDescription("Gourd must stay Locked at least this long before a Loose transition plays the theme. Prevents playing for gourds already on the ground at load.", (AcceptableValueBase)(object)new AcceptableValueRange(0.25f, 10f), Array.Empty())); LogVerbose = ((BasePlugin)this).Config.Bind("Gourdwell", "LogVerbose", false, "Extra logging."); ((BasePlugin)this).AddComponent(); ManualLogSource log = Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(41, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("Gourdwell"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" v"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted("1.0.16"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded — Reward Gourds become Maxwell."); } log.LogInfo(val); } } internal static class PurrSynth { private const int SampleRate = 44100; private const float Seconds = 0.9f; private const float Fundamental = 27f; public static AudioClip Create() { int num = 39690; float[] array = new float[num]; uint num2 = 2463534242u; float num3 = 0f; for (int i = 0; i < num; i++) { float num4 = (float)i / 44100f; float num5 = num4 * 27f; float num6 = Mathf.Exp((0f - (num5 - Mathf.Floor(num5))) * 7f) - 0.14f; num2 ^= num2 << 13; num2 ^= num2 >> 17; num2 ^= num2 << 5; float num7 = (float)(int)(num2 & 0xFFFFFF) / (26353588f / (float)Math.PI) - 1f; num3 += (num7 - num3) * 0.06f; float num8 = Mathf.Sin((float)Math.PI * Mathf.Clamp01(num4 / 0.9f)); array[i] = (num6 * 0.75f + num3 * num6 * 0.9f) * num8 * 0.5f; } AudioClip obj = AudioClip.Create("Gourdwell_Purr", num, 1, 44100, false); obj.SetData(Il2CppStructArray.op_Implicit(array), 0); return obj; } } internal static class WavLoader { public static bool TryLoad(string path, out AudioClip clip, float maxSeconds = 0f) { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown clip = null; if (!File.Exists(path)) { return false; } byte[] array = File.ReadAllBytes(path); if (array.Length < 44) { return false; } if (array[0] != 82 || array[1] != 73 || array[2] != 70 || array[3] != 70) { return false; } if (array[8] != 87 || array[9] != 65 || array[10] != 86 || array[11] != 69) { return false; } int num = 0; int num2 = 0; int num3 = 0; int num4 = -1; int num5 = 0; int num6 = 12; bool flag = default(bool); while (num6 + 8 <= array.Length) { string text = Encoding.ASCII.GetString(array, num6, 4); int num7 = BitConverter.ToInt32(array, num6 + 4); int num8 = num6 + 8; if (text == "fmt ") { short num9 = BitConverter.ToInt16(array, num8); num = BitConverter.ToInt16(array, num8 + 2); num2 = BitConverter.ToInt32(array, num8 + 4); num3 = BitConverter.ToInt16(array, num8 + 14); if (num9 != 1 || num3 != 16) { ManualLogSource log = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(44, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("WAV must be PCM 16-bit (got format="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num9); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", bits="); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num3); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")."); } log.LogError(val); return false; } } else if (text == "data") { num4 = num8; num5 = num7; break; } num6 = num8 + num7 + (num7 & 1); } if (num4 < 0 || num <= 0 || num2 <= 0) { return false; } int num10 = num5 / (num3 / 8); int num11 = num10 / num; if (maxSeconds > 0f) { int num12 = Mathf.Max(1, Mathf.FloorToInt((float)num2 * maxSeconds)); if (num11 > num12) { num11 = num12; num10 = num11 * num; } } float[] array2 = new float[num10]; for (int i = 0; i < num10; i++) { int num13 = num4 + i * 2; if (num13 + 1 >= array.Length) { break; } short num14 = (short)(array[num13] | (array[num13 + 1] << 8)); array2[i] = (float)num14 / 32768f; } clip = AudioClip.Create(Path.GetFileNameWithoutExtension(path), num11, num, num2, false); clip.SetData(Il2CppStructArray.op_Implicit(array2), 0); return true; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "BigWalk.Gourdwell"; public const string PLUGIN_NAME = "Gourdwell"; public const string PLUGIN_VERSION = "1.0.16"; }