Decompiled source of PowerfulOar v1.1.1
BepInEx/plugins/PowerfulOar/PowerfulOar.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.SceneManagement; using cakeslice; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("PowerfulOar")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: AssemblyInformationalVersion("1.1.1")] [assembly: AssemblyProduct("PowerfulOar")] [assembly: AssemblyTitle("PowerfulOar")] [assembly: AssemblyVersion("1.1.1.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 PowerfulOar { internal static class BoneIslandBfoPlacement { private const string BoneIslandSceneName = "island 36 ()"; private const float SafeSpawnDistance = 500f; private static readonly Vector3 LocalPosition = new Vector3(232.5f, 17.88f, 431.6406f); private static readonly Quaternion LocalRotation = Quaternion.Euler(-0.415f, 116.637f, 81.422f); private static readonly HashSet<int> PendingScenes = new HashSet<int>(); private static bool initialized; internal static void Initialize() { if (!initialized) { initialized = true; SceneManager.sceneLoaded += OnSceneLoaded; QueueLoadedBoneIslandScenes(); } } internal static void Shutdown() { if (initialized) { SceneManager.sceneLoaded -= OnSceneLoaded; PendingScenes.Clear(); initialized = false; } } internal static void OnPrefabsReady() { QueueLoadedBoneIslandScenes(); } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) QueueScene(scene); } private static void QueueLoadedBoneIslandScenes() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < SceneManager.sceneCount; i++) { QueueScene(SceneManager.GetSceneAt(i)); } } private static void QueueScene(Scene scene) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) PowerfulOarPlugin instance = PowerfulOarPlugin.Instance; if (!((Object)(object)instance == (Object)null) && ((Scene)(ref scene)).IsValid() && ((Scene)(ref scene)).isLoaded && !(((Scene)(ref scene)).name != "island 36 ()") && PendingScenes.Add(((Scene)(ref scene)).handle)) { ((MonoBehaviour)instance).StartCoroutine(PlaceWhenReady(scene)); } } private static IEnumerator PlaceWhenReady(Scene scene) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) int sceneHandle = ((Scene)(ref scene)).handle; Transform scenery = null; while ((Object)(object)PowerfulOarPlugin.Instance != (Object)null && ((Scene)(ref scene)).IsValid() && ((Scene)(ref scene)).isLoaded) { if ((Object)(object)scenery == (Object)null) { scenery = FindSceneryRoot(scene); } PrefabsDirectory instance = PrefabsDirectory.instance; Camera main = Camera.main; Vector3 val = (((Object)(object)scenery != (Object)null) ? scenery.TransformPoint(LocalPosition) : Vector3.zero); if (GameState.playing && !GameState.currentlyLoading && (Object)(object)scenery != (Object)null && (Object)(object)main != (Object)null && Vector3.Distance(((Component)main).transform.position, val) <= 500f && (Object)(object)instance != (Object)null && instance.directory != null && instance.directory.Length > 666 && (Object)(object)instance.directory[666] != (Object)null) { if (ScaledOarFactory.ValidateRuntimeCache(instance)) { TryPlace(instance, scenery); } PendingScenes.Remove(sceneHandle); yield break; } yield return null; } PendingScenes.Remove(sceneHandle); } private static void TryPlace(PrefabsDirectory directory, Transform scenery) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) GameObject val = directory.directory[666]; if (HasExistingRuntimeBfo(val)) { ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogInfo((object)"Skipped Bone Island BFO display: an existing collected or display BFO 5000 is already loaded."); } return; } GameObject val2 = Object.Instantiate<GameObject>(val); ShipItem component = val2.GetComponent<ShipItem>(); if ((Object)(object)component == (Object)null) { ManualLogSource logSource2 = PowerfulOarPlugin.LogSource; if (logSource2 != null) { logSource2.LogError((object)"Could not place Bone Island BFO 5000: cloned ShipItem missing."); } val2.SetActive(false); return; } ((Object)val2).name = "BFO 5000 (Bone Island)"; val2.transform.SetParent(scenery, false); val2.transform.localPosition = LocalPosition; val2.transform.localRotation = LocalRotation; component.sold = true; Good component2 = val2.GetComponent<Good>(); if ((Object)(object)component2 != (Object)null) { component2.RegisterAsMissionless(); } ItemRigidbody itemRigidbody = component.GetItemRigidbody(); val2.GetComponent<ScaledOarController>()?.SetPersistentKinematic(state: true); if ((Object)(object)itemRigidbody != (Object)null) { itemRigidbody.debugForceKinematic = true; Rigidbody component3 = ((Component)itemRigidbody).GetComponent<Rigidbody>(); if ((Object)(object)component3 != (Object)null) { component3.isKinematic = true; component3.useGravity = false; component3.velocity = Vector3.zero; component3.angularVelocity = Vector3.zero; } } BoneIslandBfoDisplay boneIslandBfoDisplay = val2.GetComponent<BoneIslandBfoDisplay>(); if ((Object)(object)boneIslandBfoDisplay == (Object)null) { boneIslandBfoDisplay = val2.AddComponent<BoneIslandBfoDisplay>(); } boneIslandBfoDisplay.Initialize(component); ManualLogSource logSource3 = PowerfulOarPlugin.LogSource; if (logSource3 != null) { logSource3.LogInfo((object)("Placed one fixed BFO 5000 at the configured Bone Island _scenery-local pose. It will enter normal item/save control when picked up. " + $"Camera was within {500f:0} m of the placement.")); } } private static bool HasExistingRuntimeBfo(GameObject registeredPrefab) { SaveablePrefab[] array = Resources.FindObjectsOfTypeAll<SaveablePrefab>(); foreach (SaveablePrefab val in array) { if ((Object)(object)val != (Object)null && val.prefabIndex == 666 && (Object)(object)((Component)val).gameObject != (Object)(object)registeredPrefab) { return true; } } return false; } private static Transform FindSceneryRoot(Scene scene) { GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); foreach (GameObject val in rootGameObjects) { if (((Object)val).name == "_scenery") { return val.transform; } } return null; } } internal sealed class BoneIslandBfoDisplay : MonoBehaviour { private ShipItem item; private ItemRigidbody itemBody; private SaveablePrefab saveable; internal void Initialize(ShipItem newItem) { item = newItem; itemBody = (((Object)(object)item != (Object)null) ? item.GetItemRigidbody() : null); saveable = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<SaveablePrefab>() : null); } private void Update() { if ((Object)(object)item == (Object)null || !Object.op_Implicit((Object)(object)((PickupableItem)item).held)) { return; } SaveablePrefab obj = saveable; if (obj != null) { obj.RegisterToSave(); } if ((Object)(object)itemBody != (Object)null) { ScaledOarController component = ((Component)item).GetComponent<ScaledOarController>(); if ((Object)(object)component != (Object)null) { component.SetPersistentKinematic(state: false); } else { itemBody.debugForceKinematic = false; } Rigidbody component2 = ((Component)itemBody).GetComponent<Rigidbody>(); if ((Object)(object)component2 != (Object)null) { component2.useGravity = true; } } if ((Object)(object)FloatingOriginManager.instance != (Object)null) { ((Component)this).transform.SetParent(((Component)FloatingOriginManager.instance).transform, true); } ((Behaviour)this).enabled = false; ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogInfo((object)"Released the Bone Island BFO 5000 to normal held-item physics and saving."); } } } internal static class RadRefinementCompatibility { internal const string PluginGuid = "com.raddude.radrefinements"; private const string ConfigsTypeName = "RadRefinements.Configs"; private static ConfigEntry<float> rowingNeedsReduction; private static ConfigEntry<bool> continualRow; private static bool needsReductionEnabled; private static bool continualRowAvailable; internal static bool NeedsReductionEnabled => needsReductionEnabled; internal static bool ContinualRowAvailable => continualRowAvailable; internal static float NeedsCostMultiplier { get { if (!needsReductionEnabled || rowingNeedsReduction == null) { return 1f; } return 1f - Mathf.Clamp01(rowingNeedsReduction.Value); } } internal static bool ContinualRowEnabled { get { if (continualRowAvailable && continualRow != null) { return continualRow.Value; } return false; } } internal static void Initialize(Harmony harmony) { rowingNeedsReduction = null; continualRow = null; needsReductionEnabled = false; continualRowAvailable = false; Type type = AccessTools.TypeByName("RadRefinements.Configs"); if (type == null) { return; } rowingNeedsReduction = AccessTools.Field(type, "rowingNeedsMult")?.GetValue(null) as ConfigEntry<float>; continualRow = AccessTools.Field(type, "continualRow")?.GetValue(null) as ConfigEntry<bool>; MethodBase methodBase = AccessTools.DeclaredMethod(typeof(ShipItemOar), "ExtraLateUpdate", (Type[])null, (Type[])null); MethodBase methodBase2 = AccessTools.DeclaredMethod(typeof(ShipItemOar), "OnAltHeld", (Type[])null, (Type[])null); Patches val = ((methodBase != null) ? Harmony.GetPatchInfo(methodBase) : null); Patches val2 = ((methodBase2 != null) ? Harmony.GetPatchInfo(methodBase2) : null); MethodInfo methodInfo = FindOwnedPatch(val?.Prefixes, "ReduceNeedsPrefix"); MethodInfo methodInfo2 = FindOwnedPatch(val?.Postfixes, "ReduceNeedsPostfix"); MethodInfo patchMethod = FindOwnedPatch(val2?.Postfixes, "ContinualRow", "Postfix"); continualRowAvailable = continualRow != null && ContainsPatch(methodBase2, patchMethod); if (harmony == null || rowingNeedsReduction == null || !ContainsPatch(methodBase, methodInfo) || !ContainsPatch(methodBase, methodInfo2)) { ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogWarning((object)"RadRefinement was detected, but its rowing-needs patches could not be safely replaced. Set RadRefinement's Rowing needs reduction to 0 to avoid incorrect needs costs."); } LogContinualRowStatus(); return; } try { harmony.Unpatch(methodBase, methodInfo); harmony.Unpatch(methodBase, methodInfo2); needsReductionEnabled = !ContainsPatch(methodBase, methodInfo) && !ContainsPatch(methodBase, methodInfo2); if (needsReductionEnabled) { ManualLogSource logSource2 = PowerfulOarPlugin.LogSource; if (logSource2 != null) { logSource2.LogInfo((object)"RadRefinement rowing-needs compatibility enabled: its reduction slider now scales PowerfulOar baselines."); } } else { ManualLogSource logSource3 = PowerfulOarPlugin.LogSource; if (logSource3 != null) { logSource3.LogError((object)"RadRefinement rowing-needs patches remained installed; slider compatibility was disabled."); } } } catch (Exception ex) { needsReductionEnabled = false; ManualLogSource logSource4 = PowerfulOarPlugin.LogSource; if (logSource4 != null) { logSource4.LogError((object)("Could not install RadRefinement rowing-needs compatibility: " + ex)); } } LogContinualRowStatus(); } private static void LogContinualRowStatus() { if (continualRowAvailable) { ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogInfo((object)"RadRefinement continual-row force compatibility enabled."); } } else if (continualRow != null) { ManualLogSource logSource2 = PowerfulOarPlugin.LogSource; if (logSource2 != null) { logSource2.LogWarning((object)"RadRefinement's continual-row patch could not be safely identified. Disable its Row continually option to avoid incorrect rowing force."); } } } private static MethodInfo FindOwnedPatch(IEnumerable<Patch> patches, params string[] acceptedMethodNames) { if (patches == null) { return null; } MethodInfo methodInfo = null; foreach (Patch patch in patches) { MethodInfo patchMethod = patch.PatchMethod; if (patch.owner != "com.raddude.radrefinements" || patchMethod == null || !HasAcceptedName(patchMethod, acceptedMethodNames)) { continue; } if (methodInfo != null && !object.Equals(methodInfo, patchMethod)) { ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogWarning((object)"Found multiple RadRefinement rowing patches where exactly one was expected; compatibility was disabled."); } return null; } methodInfo = patchMethod; } return methodInfo; } private static bool HasAcceptedName(MethodInfo method, IEnumerable<string> acceptedMethodNames) { foreach (string acceptedMethodName in acceptedMethodNames) { if (string.Equals(method.Name, acceptedMethodName, StringComparison.Ordinal)) { return true; } } return false; } private static bool ContainsPatch(MethodBase target, MethodInfo patchMethod) { if (target == null || patchMethod == null) { return false; } Patches patchInfo = Harmony.GetPatchInfo(target); if (patchInfo == null) { return false; } if (!ContainsPatch(patchInfo.Prefixes, patchMethod) && !ContainsPatch(patchInfo.Postfixes, patchMethod) && !ContainsPatch(patchInfo.Transpilers, patchMethod)) { return ContainsPatch(patchInfo.Finalizers, patchMethod); } return true; } private static bool ContainsPatch(IEnumerable<Patch> patches, MethodInfo patchMethod) { foreach (Patch patch in patches) { if (patch.PatchMethod == patchMethod) { return true; } } return false; } } internal static class HookHangMoreCompatibility { internal const string PluginGuid = "com.raddude.hookshangmore"; private const string AttachableItemTypeName = "HooksHangMore.AttachableItem"; internal static bool IsExcluded(ShipItem item) { return OarStats.IsScaledOar(item); } internal static void Exclude(ShipItem item) { if (!IsExcluded(item)) { return; } HangableItem component = ((Component)item).GetComponent<HangableItem>(); if ((Object)(object)component != (Object)null && ((Behaviour)component).enabled) { component.DisconnectJoint(); ((Behaviour)component).enabled = false; ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogInfo((object)("Disabled vanilla hook hanging for " + item.name + ".")); } } Type type = AccessTools.TypeByName("HooksHangMore.AttachableItem"); Component val = ((type != null) ? ((Component)item).GetComponent(type) : null); if (!((Object)(object)val == (Object)null)) { Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null); if ((Object)(object)val2 != (Object)null) { val2.enabled = false; } Object.Destroy((Object)(object)val); ManualLogSource logSource2 = PowerfulOarPlugin.LogSource; if (logSource2 != null) { logSource2.LogInfo((object)("Removed HooksHangMore attachment support from " + item.name + ".")); } } } } internal static class HugeOarPurchaseState { private const string SaveKey = "DogEggz.PowerfulOar.HugeOarPurchases.v1"; private static int purchaseCount; internal static void Reset() { purchaseCount = 0; } internal static void Load() { Reset(); if (GameState.modData == null || !GameState.modData.TryGetValue("DogEggz.PowerfulOar.HugeOarPurchases.v1", out var value)) { return; } if (!int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out var result) || result < 0) { ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogWarning((object)"Ignored invalid Huge Oar purchase count in this save."); } } else { purchaseCount = result; } } internal static int RecordPurchase() { if (purchaseCount < int.MaxValue) { purchaseCount++; } Store(); return purchaseCount; } internal static string GetDialogue(int count) { if (count <= 1) { return "...What do you even need this for?"; } if (count == 2) { return "These things actually sell? I'm a genius!"; } return "I'm gonna need a lot more logs..."; } internal static void Store() { if (GameState.modData == null) { GameState.modData = new Dictionary<string, string>(); } GameState.modData["DogEggz.PowerfulOar.HugeOarPurchases.v1"] = purchaseCount.ToString(CultureInfo.InvariantCulture); } internal static void ClearBeforeLoad() { Reset(); GameState.modData?.Remove("DogEggz.PowerfulOar.HugeOarPurchases.v1"); } } internal sealed class HugeOarDialogue { private static GameObject template; private static string textPath; private static string buttonPath; private readonly GameObject panel; private readonly Transform bubble; private HugeOarDialogue(GameObject newPanel, Transform newBubble) { panel = newPanel; bubble = newBubble; } internal static void Capture(TavernRumorsDude source) { //IL_00c6: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)template != (Object)null) && !((Object)(object)source == (Object)null) && !((Object)(object)source.speechUI == (Object)null) && !((Object)(object)source.text == (Object)null) && !((Object)(object)source.drinkButton == (Object)null)) { textPath = Path(source.speechUI.transform, ((Component)source.text).transform); buttonPath = Path(source.speechUI.transform, source.drinkButton.transform); template = Object.Instantiate<GameObject>(source.speechUI); ((Object)template).name = "PowerfulOar Huge Oar dialogue template"; template.SetActive(false); template.transform.SetParent((Transform)null, false); template.transform.localScale = Vector3.one; MonoBehaviour[] componentsInChildren = template.GetComponentsInChildren<MonoBehaviour>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } if (Application.isPlaying) { Object.DontDestroyOnLoad((Object)(object)template); } } } internal static HugeOarDialogue Create(Transform parent, string content) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0121: 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_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)template == (Object)null) { TavernRumorsDude[] array = Resources.FindObjectsOfTypeAll<TavernRumorsDude>(); foreach (TavernRumorsDude val in array) { Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { Capture(val); if ((Object)(object)template != (Object)null) { break; } } } } if ((Object)(object)template == (Object)null) { return null; } GameObject val2 = Object.Instantiate<GameObject>(template, parent, false); ((Object)val2).name = "Huge Oar purchase dialogue"; val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; val2.transform.localScale = Vector3.one; TextMesh component = ((Component)val2.transform.Find(textPath)).GetComponent<TextMesh>(); Transform parent2 = ((Component)component).transform.parent; Transform val3 = parent2.Find("gfx"); Transform val4 = val2.transform.Find(buttonPath); val2.SetActive(true); ((Component)val4).gameObject.SetActive(false); Renderer component2 = ((Component)component).GetComponent<Renderer>(); Bounds bounds = component2.bounds; Vector3 size = ((Bounds)(ref bounds)).size; bounds = ((Component)val3).GetComponent<Renderer>().bounds; Vector3 size2 = ((Bounds)(ref bounds)).size; string text = Wrap(content, 40); component.font.RequestCharactersInTexture(text, component.fontSize, component.fontStyle); component.text = text; bounds = component2.bounds; Vector3 size3 = ((Bounds)(ref bounds)).size; Vector3 localScale = val3.localScale; localScale.x *= Mathf.Max(0.35f, (size2.x + size3.x - size.x) / Mathf.Max(0.001f, size2.x)); localScale.y *= Mathf.Max(1f, (size2.y + size3.y - size.y) / Mathf.Max(0.001f, size2.y)); val3.localScale = localScale; Collider[] componentsInChildren = val2.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } val2.SetActive(false); return new HugeOarDialogue(val2, parent2); } internal static void Shutdown() { if ((Object)(object)template != (Object)null) { Object.Destroy((Object)(object)template); template = null; } textPath = null; buttonPath = null; } internal void Show(Transform anchor) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_006e: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)panel == (Object)null) && !((Object)(object)anchor == (Object)null) && !((Object)(object)Refs.observerMirror == (Object)null)) { Transform transform = ((Component)Refs.observerMirror).transform; Vector3 val = Vector3.ProjectOnPlane(transform.position - anchor.position, Vector3.up); Vector3 normalized = ((Vector3)(ref val)).normalized; Vector3 val2 = anchor.position + normalized * 0.75f; val2.y = transform.position.y + 1.2f - bubble.localPosition.y; panel.transform.SetPositionAndRotation(val2, transform.rotation); panel.SetActive(true); } } internal void Hide() { if ((Object)(object)panel != (Object)null) { panel.SetActive(false); } } internal void Dispose() { if ((Object)(object)panel != (Object)null) { Object.Destroy((Object)(object)panel); } } private static string Path(Transform root, Transform child) { List<string> list = new List<string>(); while ((Object)(object)child != (Object)null && (Object)(object)child != (Object)(object)root) { list.Add(((Object)child).name); child = child.parent; } if ((Object)(object)child != (Object)(object)root) { throw new InvalidOperationException("Dialogue element is outside the speech UI."); } list.Reverse(); return string.Join("/", list.ToArray()); } private static string Wrap(string value, int width) { value = value.TrimStart(Array.Empty<char>()); if (value.Length <= width) { return value; } int num = value.LastIndexOf(' ', width); if (num < 1) { num = width; } return value.Substring(0, num) + "\n" + Wrap(value.Substring(num), width); } } internal sealed class HugeOarPurchaseDialogueArea : MonoBehaviour { private const float OpenDistance = 4f; private const float CloseDistance = 5f; private readonly HashSet<Collider> players = new HashSet<Collider>(); private Transform source; private Rigidbody body; private Collider trigger; private HugeOarDialogue dialogue; private string content; private float retry; private bool pending; private bool open; private bool missingDialogueLogged; internal static HugeOarPurchaseDialogueArea Create(Transform source) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_0051: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("PowerfulOar Huge Oar purchase dialogue trigger"); try { val.SetActive(false); SceneManager.MoveGameObjectToScene(val, ((Component)source).gameObject.scene); val.layer = 2; val.transform.position = source.position; val.transform.rotation = Quaternion.identity; val.transform.localScale = Vector3.one; Rigidbody obj = val.AddComponent<Rigidbody>(); obj.isKinematic = true; obj.useGravity = false; SphereCollider obj2 = val.AddComponent<SphereCollider>(); obj2.radius = 4f; ((Collider)obj2).isTrigger = true; HugeOarPurchaseDialogueArea hugeOarPurchaseDialogueArea = val.AddComponent<HugeOarPurchaseDialogueArea>(); hugeOarPurchaseDialogueArea.source = source; val.SetActive(true); return hugeOarPurchaseDialogueArea; } catch { val.SetActive(false); Object.Destroy((Object)(object)val); throw; } } internal void ShowPurchase(string newContent) { content = newContent; pending = true; retry = 0f; missingDialogueLogged = false; dialogue?.Dispose(); dialogue = null; float num = ObserverDistance(); open = num <= 4f; } private void Awake() { body = ((Component)this).GetComponent<Rigidbody>(); trigger = ((Component)this).GetComponent<Collider>(); } private void FixedUpdate() { //IL_0060: 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) if ((Object)(object)source == (Object)null) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } trigger.enabled = ((Component)source).gameObject.activeInHierarchy; if (!trigger.enabled || GameState.currentlyLoading) { players.Clear(); } body.position = source.position; body.rotation = Quaternion.identity; } private void Update() { players.RemoveWhere((Collider player) => (Object)(object)player == (Object)null || !((Component)player).gameObject.activeInHierarchy); if (!pending || !Available()) { dialogue?.Hide(); return; } float num = ObserverDistance(); if (!open && players.Count > 0 && num <= 4f) { open = true; } if (open && num > 5f) { ClosePurchase(); return; } if (!open) { dialogue?.Hide(); return; } if (dialogue == null && Time.unscaledTime >= retry) { retry = Time.unscaledTime + 0.5f; dialogue = HugeOarDialogue.Create(((Component)this).transform, content); if (dialogue == null && !missingDialogueLogged) { missingDialogueLogged = true; ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogError((object)"Huge Oar was purchased, but the vanilla dialogue template is not available yet; retrying."); } } } dialogue?.Show(source); } private void OnTriggerEnter(Collider other) { Observe(other); } private void OnTriggerStay(Collider other) { Observe(other); } private void OnTriggerExit(Collider other) { players.Remove(other); } private void OnDisable() { dialogue?.Hide(); } private void OnDestroy() { dialogue?.Dispose(); dialogue = null; } private void Observe(Collider other) { if (((Component)other).CompareTag("Player")) { players.Add(other); } } private bool Available() { if ((Object)(object)source != (Object)null && ((Component)source).gameObject.activeInHierarchy && (Object)(object)Refs.observerMirror != (Object)null && !GameState.currentlyLoading && !GameState.justStarted && !GameState.recovering) { return !GameState.sleeping; } return false; } private float ObserverDistance() { //IL_002b: 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) if (!((Object)(object)Refs.observerMirror != (Object)null) || !((Object)(object)source != (Object)null)) { return float.PositiveInfinity; } return Vector3.Distance(((Component)Refs.observerMirror).transform.position, source.position); } private void ClosePurchase() { pending = false; open = false; content = null; dialogue?.Dispose(); dialogue = null; } } [HarmonyPatch(typeof(TavernRumorsDude), "Awake")] internal static class HugeOarDialogueCapturePatch { [HarmonyPostfix] private static void Postfix(TavernRumorsDude __instance) { HugeOarDialogue.Capture(__instance); } } [HarmonyPatch(typeof(Shopkeeper), "SellItem")] internal static class HugeOarPurchasePatch { [HarmonyPostfix] private static void Postfix(Shopkeeper __instance, ShipItem item) { if (HugeOarVendorPatch.IsTarget(__instance) && OarStats.GetPrefabIndex(item) == 603) { int purchaseCount = HugeOarPurchaseState.RecordPurchase(); ((Component)__instance).GetComponent<HugeOarVendorInstaller>()?.ShowPurchaseReaction(purchaseCount); ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogInfo((object)("Kicia Bay Huge Oar purchase count is now " + purchaseCount + ".")); } } } } [HarmonyPatch(typeof(SaveLoadManager), "Awake")] internal static class HugeOarPurchaseSessionPatch { [HarmonyPrefix] private static void Prefix() { HugeOarPurchaseState.Reset(); } } [HarmonyPatch(typeof(SaveLoadManager), "LoadGame")] internal static class HugeOarPurchaseLoadGamePatch { [HarmonyPrefix] private static void Prefix() { HugeOarPurchaseState.ClearBeforeLoad(); } } [HarmonyPatch(typeof(SaveLoadManager), "LoadModData")] internal static class HugeOarPurchaseLoadPatch { [HarmonyPostfix] private static void Postfix() { HugeOarPurchaseState.Load(); } } [HarmonyPatch(typeof(SaveLoadManager), "SaveModData")] internal static class HugeOarPurchaseStorePatch { [HarmonyPrefix] private static void Prefix() { HugeOarPurchaseState.Store(); } } [BepInPlugin("DogEggz.PowerfulOar", "PowerfulOar", "1.1.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class PowerfulOarPlugin : BaseUnityPlugin { private sealed class PatchTarget { internal Type PatchType { get; } internal Type TargetType { get; } internal string TargetMethodName { get; } internal Type[] ArgumentTypes { get; } internal PatchTarget(Type patchType, Type targetType, string targetMethodName, Type[] argumentTypes = null) { PatchType = patchType; TargetType = targetType; TargetMethodName = targetMethodName; ArgumentTypes = argumentTypes; } } public const string PluginGuid = "DogEggz.PowerfulOar"; public const string PluginName = "PowerfulOar"; public const string PluginVersion = "1.1.1"; internal const string GoPointerInputLoopMethod = "LateUpdate"; private Harmony harmony; private readonly List<Harmony> featureHarmonies = new List<Harmony>(); internal static PowerfulOarPlugin Instance { get; private set; } internal static ManualLogSource LogSource { get; private set; } private void Awake() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown Instance = this; LogSource = ((BaseUnityPlugin)this).Logger; harmony = new Harmony("DogEggz.PowerfulOar"); RadRefinementCompatibility.Initialize(harmony); bool flag = ApplyPatchClass(typeof(OarStatsPatch), typeof(ShipItemOar), "OnAltHeld"); bool flag2 = ApplyPatchClass(typeof(OarLateUpdatePatch), typeof(ShipItemOar), "ExtraLateUpdate"); bool flag3 = ApplyPatchGroup("runtime_lifecycle", new PatchTarget(typeof(ScaledOarRigidbodyScalePatch), typeof(ItemRigidbody), "LateUpdate"), new PatchTarget(typeof(ScaledOarSavedStatePatch), typeof(SaveablePrefab), "Load", new Type[1] { typeof(SavePrefabData) }), new PatchTarget(typeof(ScaledOarInventoryEnterPatch), typeof(ItemRigidbody), "EnterInventorySlot", new Type[1] { typeof(Transform) }), new PatchTarget(typeof(ScaledOarInventoryExitPatch), typeof(ItemRigidbody), "ExitInventorySlot")); bool flag4 = flag3 && ApplyPatchClass(typeof(ScaledOarPrefabRegistrationPatch), typeof(PrefabsDirectory), "Start"); bool flag5 = ApplyPatchClass(typeof(ScaledOarOutlineEffectPatch), typeof(OutlineEffect), "OnEnable"); bool flag6 = ApplyPatchClass(typeof(ReverseOarInputPatch), typeof(GoPointer), "LateUpdate"); bool flag7 = ApplyPatchClass(typeof(ScaledOarNailingPatch), typeof(ShipItemHammer), "CanNail", new Type[1] { typeof(ShipItem) }); bool flag8 = flag4 && ApplyPatchGroup("vendor_display", new PatchTarget(typeof(BigOarVendorPatch), typeof(ShopItemSpawner), "Start"), new PatchTarget(typeof(ScaledOarVendorSpawnPatch), typeof(ShopItemSpawner), "SpawnItem"), new PatchTarget(typeof(HugeOarVendorPatch), typeof(Shopkeeper), "Start")); bool flag9 = flag8 && ApplyPatchGroup("huge_oar_dialogue", new PatchTarget(typeof(HugeOarDialogueCapturePatch), typeof(TavernRumorsDude), "Awake"), new PatchTarget(typeof(HugeOarPurchasePatch), typeof(Shopkeeper), "SellItem", new Type[3] { typeof(ShipItem), typeof(int), typeof(int) }), new PatchTarget(typeof(HugeOarPurchaseSessionPatch), typeof(SaveLoadManager), "Awake"), new PatchTarget(typeof(HugeOarPurchaseLoadGamePatch), typeof(SaveLoadManager), "LoadGame", new Type[1] { typeof(int) }), new PatchTarget(typeof(HugeOarPurchaseLoadPatch), typeof(SaveLoadManager), "LoadModData"), new PatchTarget(typeof(HugeOarPurchaseStorePatch), typeof(SaveLoadManager), "SaveModData")); bool flag10 = ApplyPatchClass(typeof(HookHangMoreExclusionPatch), typeof(ShipItem), "Awake"); bool flag11 = flag4 && ApplyPatchGroup("crate_blocker", new PatchTarget(typeof(ScaledOarCrateInsertPatch), typeof(CrateInventory), "InsertItem", new Type[1] { typeof(ShipItem) }), new PatchTarget(typeof(ScaledOarCrateWithdrawPatch), typeof(CrateInventory), "WithdrawItem", new Type[1] { typeof(ShipItem) }), new PatchTarget(typeof(ScaledOarCrateUiPatch), typeof(CrateInventoryButton), "OnActivate", new Type[1] { typeof(GoPointer) })); if (flag4) { BoneIslandBfoPlacement.Initialize(); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("PowerfulOar 1.1.1 loaded. Fixed per-oar stats and needs costs enabled. Hold Q to row opposite vanilla. Bone Island BFO placement, scaled-oar vendor displays, and Kicia Bay Huge Oar enabled. " + $"Patches: stats={flag}, late update={flag2}, " + $"prefab={flag4}, outline wake fix={flag5}, " + $"reverse input={flag6}, nailing={flag7}, " + $"vendor display group={flag8}, " + $"Huge Oar dialogue group={flag9}, " + $"HookHangMore exclusion={flag10}, " + $"scaled-oar lifecycle group={flag3}, " + $"crate blocker group={flag11}, " + $"RadRefinement needs={RadRefinementCompatibility.NeedsReductionEnabled}, " + $"continual row={RadRefinementCompatibility.ContinualRowAvailable}.")); } private bool ApplyPatchClass(Type patchType, Type targetType, string targetMethodName, Type[] argumentTypes = null) { if (AccessTools.DeclaredMethod(targetType, targetMethodName, argumentTypes ?? Type.EmptyTypes, (Type[])null) == null) { ((BaseUnityPlugin)this).Logger.LogError((object)("Skipped " + patchType.Name + ": target method " + targetType.FullName + "." + targetMethodName + " was not found.")); return false; } try { harmony.PatchAll(patchType); return true; } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failed to apply " + patchType.Name + " to " + $"{targetType.FullName}.{targetMethodName}: {arg}")); return false; } } private bool ApplyPatchGroup(string groupName, params PatchTarget[] targets) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown PatchTarget[] array = targets; foreach (PatchTarget patchTarget in array) { if (AccessTools.DeclaredMethod(patchTarget.TargetType, patchTarget.TargetMethodName, patchTarget.ArgumentTypes ?? Type.EmptyTypes, (Type[])null) == null) { ((BaseUnityPlugin)this).Logger.LogError((object)("Skipped patch group '" + groupName + "': target method " + patchTarget.TargetType.FullName + "." + patchTarget.TargetMethodName + " was not found.")); return false; } } Harmony val = new Harmony("DogEggz.PowerfulOar." + groupName); try { array = targets; foreach (PatchTarget patchTarget2 in array) { val.PatchAll(patchTarget2.PatchType); } featureHarmonies.Add(val); return true; } catch (Exception arg) { val.UnpatchSelf(); ((BaseUnityPlugin)this).Logger.LogError((object)("Failed to apply patch group '" + groupName + "'; all patches in " + $"the group were rolled back: {arg}")); return false; } } private void OnDestroy() { BoneIslandBfoPlacement.Shutdown(); HugeOarDialogue.Shutdown(); HugeOarPurchaseState.Reset(); foreach (Harmony featureHarmony in featureHarmonies) { featureHarmony.UnpatchSelf(); } featureHarmonies.Clear(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; LogSource = null; } } } internal static class PowerfulOarInput { internal static bool ReverseRowHeld { get { if (GameState.playing && !GameState.inCursorMenu && !GameState.wasInSettingsMenu) { return Input.GetKey((KeyCode)113); } return false; } } } [HarmonyPatch(typeof(GoPointer), "LateUpdate")] internal static class ReverseOarInputPatch { [HarmonyPostfix] private static void Postfix(GoPointer __instance) { if (!PowerfulOarInput.ReverseRowHeld) { return; } PickupableItem heldItem = __instance.GetHeldItem(); ShipItemOar val = (ShipItemOar)(object)((heldItem is ShipItemOar) ? heldItem : null); if (!((Object)(object)val == (Object)null) && !GameInput.GetKey((InputName)9)) { if (Input.GetKeyDown((KeyCode)113)) { ((GoPointerButton)val).OnAltActivate(); } ((GoPointerButton)val).OnAltHeld(); } } } [HarmonyPatch(typeof(ShipItemOar), "OnAltHeld")] internal static class OarStatsPatch { private struct RowCallState { internal float ProgressBefore; internal bool Reverse; } [HarmonyPrefix] private static bool Prefix(ShipItemOar __instance, ref bool ___isHoldingButton, bool ___isOverWater, ref bool ___isRowing, ref float ___rowProgress, out RowCallState __state) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00c0: 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_00d1: Unknown result type (might be due to invalid IL or missing references) __state = new RowCallState { ProgressBefore = ___rowProgress, Reverse = PowerfulOarInput.ReverseRowHeld }; OarStats.Apply(__instance); if (!__state.Reverse) { return true; } ___isHoldingButton = true; if (Object.op_Implicit((Object)(object)((PickupableItem)__instance).held) && ___isOverWater && Object.op_Implicit((Object)(object)GameState.currentBoat)) { if (___rowProgress <= 1f) { ___isRowing = true; ___rowProgress += Time.deltaTime; Rigidbody component = ((Component)GameState.currentBoat.parent).GetComponent<Rigidbody>(); float maxBoatSpeed = __instance.maxBoatSpeed; Vector3 velocity = component.velocity; float num = Mathf.InverseLerp(maxBoatSpeed, 0f, ((Vector3)(ref velocity)).magnitude); component.AddForceAtPosition(__instance.waterPos.forward * __instance.rowForce * Time.deltaTime * num, __instance.waterPos.position); } else { ___isRowing = false; } } return false; } [HarmonyPostfix] [HarmonyAfter(new string[] { "com.raddude.radrefinements" })] private static void Postfix(ShipItemOar __instance, bool ___isOverWater, RowCallState __state) { //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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_0084: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) if (RadRefinementCompatibility.ContinualRowEnabled && Object.op_Implicit((Object)(object)((PickupableItem)__instance).held) && ___isOverWater && Object.op_Implicit((Object)(object)GameState.currentBoat) && !(__state.ProgressBefore > 1f) && !(__state.ProgressBefore + Time.deltaTime > 1f)) { Rigidbody component = ((Component)GameState.currentBoat.parent).GetComponent<Rigidbody>(); Vector3 val = __instance.waterPos.forward * (0f - __instance.rowForce) * Time.deltaTime; component.AddForceAtPosition(-val, __instance.waterPos.position); float maxBoatSpeed = __instance.maxBoatSpeed; Vector3 velocity = component.velocity; float num = Mathf.InverseLerp(maxBoatSpeed, 0f, ((Vector3)(ref velocity)).magnitude); float num2 = (__state.Reverse ? 1f : (-1f)); component.AddForceAtPosition(__instance.waterPos.forward * __instance.rowForce * Time.deltaTime * num * num2, __instance.waterPos.position); } } } [HarmonyPatch(typeof(ShipItemOar), "ExtraLateUpdate")] internal static class OarLateUpdatePatch { private const float VanillaWaterCost = 0.4f; private const float VanillaFoodCost = 0.6f; [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); FieldInfo needsField = AccessTools.Field(typeof(PlayerNeeds), "water"); FieldInfo needsField2 = AccessTools.Field(typeof(PlayerNeeds), "food"); FieldInfo rowProgressField = AccessTools.Field(typeof(ShipItemOar), "rowProgress"); List<int> list2 = FindNeedCostConstants(list, needsField, 0.4f); List<int> list3 = FindNeedCostConstants(list, needsField2, 0.6f); if (list2.Count == 1 && list3.Count == 1) { MethodInfo selector = AccessTools.Method(typeof(OarLateUpdatePatch), "SelectWaterCost", (Type[])null, (Type[])null); MethodInfo selector2 = AccessTools.Method(typeof(OarLateUpdatePatch), "SelectFoodCost", (Type[])null, (Type[])null); ReplaceNeedCostConstant(list, list3[0], selector2); ReplaceNeedCostConstant(list, list2[0], selector); ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogInfo((object)"Patched per-oar rowing water and food costs: Original=0.1/s, Big Oar=0.2/s, Huge Oar=0.3/s, BFO 5000=1/s."); } } else { ManualLogSource logSource2 = PowerfulOarPlugin.LogSource; if (logSource2 != null) { logSource2.LogError((object)("Could not safely patch rowing needs costs: " + $"water matches={list2.Count}, food matches={list3.Count}. " + "Vanilla needs costs were left unchanged.")); } } List<int> list4 = FindStrokeProgressLoads(list, rowProgressField); if (list4.Count == 1) { MethodInfo methodInfo = AccessTools.Method(typeof(OarLateUpdatePatch), "SelectStrokeProgress", (Type[])null, (Type[])null); list.Insert(list4[0] + 1, new CodeInstruction(OpCodes.Call, (object)methodInfo)); ManualLogSource logSource3 = PowerfulOarPlugin.LogSource; if (logSource3 != null) { logSource3.LogInfo((object)"Patched reverse oar stroke animation for the Q key."); } } else { ManualLogSource logSource4 = PowerfulOarPlugin.LogSource; if (logSource4 != null) { logSource4.LogError((object)("Could not safely patch reverse oar stroke animation: " + $"matches={list4.Count}. Reverse thrust remains available on Q.")); } } return list; } private static float SelectStrokeProgress(float progress) { if (!PowerfulOarInput.ReverseRowHeld) { return progress; } return 1f - progress; } private static float SelectWaterCost(ShipItemOar oar) { return OarStats.GetWaterCostPerSecond(oar); } private static float SelectFoodCost(ShipItemOar oar) { return OarStats.GetFoodCostPerSecond(oar); } private static void ReplaceNeedCostConstant(IList<CodeInstruction> codes, int constantIndex, MethodInfo selector) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown CodeInstruction obj = codes[constantIndex]; obj.opcode = OpCodes.Ldarg_0; obj.operand = null; codes.Insert(constantIndex + 1, new CodeInstruction(OpCodes.Call, (object)selector)); } private static List<int> FindNeedCostConstants(IList<CodeInstruction> codes, FieldInfo needsField, float expectedConstant) { List<int> list = new List<int>(); for (int i = 0; i <= codes.Count - 6; i++) { if (!(codes[i].opcode != OpCodes.Ldsfld) && object.Equals(codes[i].operand, needsField) && !(codes[i + 2].opcode != OpCodes.Ldc_R4) && codes[i + 2].operand is float num && Mathf.Approximately(num, expectedConstant) && !(codes[i + 3].opcode != OpCodes.Mul) && !(codes[i + 4].opcode != OpCodes.Sub) && !(codes[i + 5].opcode != OpCodes.Stsfld) && object.Equals(codes[i + 5].operand, needsField)) { list.Add(i + 2); } } return list; } private static List<int> FindStrokeProgressLoads(IList<CodeInstruction> codes, FieldInfo rowProgressField) { List<int> list = new List<int>(); for (int i = 0; i <= codes.Count - 6; i++) { if (LoadsFloat(codes[i], -1f) && LoadsFloat(codes[i + 1], 2f) && !(codes[i + 2].opcode != OpCodes.Ldarg_0) && !(codes[i + 3].opcode != OpCodes.Ldfld) && object.Equals(codes[i + 3].operand, rowProgressField) && !(codes[i + 4].opcode != OpCodes.Mul) && !(codes[i + 5].opcode != OpCodes.Add)) { list.Add(i + 3); } } return list; } private static bool LoadsFloat(CodeInstruction instruction, float expected) { if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num) { return Mathf.Approximately(num, expected); } return false; } } internal static class OarStats { internal const float OriginalForce = 36000f; internal const float OriginalMaxBoatSpeed = 2.06f; internal const float OriginalNeedsCostPerSecond = 0.1f; internal const float BigForce = 93500f; internal const float BigMaxBoatSpeed = 3.1f; internal const float BigNeedsCostPerSecond = 0.2f; internal const float HugeForce = 204000f; internal const float HugeMaxBoatSpeed = 5.14f; internal const float HugeNeedsCostPerSecond = 0.3f; internal const float Bfo5000Force = 510000f; internal const float Bfo5000MaxBoatSpeed = 10.29f; internal const float Bfo5000NeedsCostPerSecond = 1f; internal static bool Apply(ShipItemOar oar) { switch (GetPrefabIndex((ShipItem)(object)oar)) { case 168: oar.rowForce = 36000f; oar.maxBoatSpeed = 2.06f; return true; case 602: oar.rowForce = 93500f; oar.maxBoatSpeed = 3.1f; return true; case 169: if (!IsLegacyBigOar((ShipItem)(object)oar)) { return false; } oar.rowForce = 93500f; oar.maxBoatSpeed = 3.1f; return true; case 603: oar.rowForce = 204000f; oar.maxBoatSpeed = 5.14f; return true; case 666: oar.rowForce = 510000f; oar.maxBoatSpeed = 10.29f; return true; default: return false; } } internal static float GetWaterCostPerSecond(ShipItemOar oar) { return GetNeedsCostPerSecond(oar, 0.4f) * RadRefinementCompatibility.NeedsCostMultiplier; } internal static float GetFoodCostPerSecond(ShipItemOar oar) { return GetNeedsCostPerSecond(oar, 0.6f) * RadRefinementCompatibility.NeedsCostMultiplier; } private static float GetNeedsCostPerSecond(ShipItemOar oar, float fallback) { switch (GetPrefabIndex((ShipItem)(object)oar)) { case 168: return 0.1f; case 602: return 0.2f; case 169: if (!IsLegacyBigOar((ShipItem)(object)oar)) { return fallback; } return 0.2f; case 603: return 0.3f; case 666: return 1f; default: return fallback; } } internal static int GetPrefabIndex(ShipItem item) { SaveablePrefab val = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<SaveablePrefab>() : null); if (!((Object)(object)val != (Object)null)) { return -1; } return val.prefabIndex; } internal static bool IsScaledOar(ShipItem item) { int prefabIndex = GetPrefabIndex(item); if (prefabIndex != 602 && !IsLegacyBigOar(item) && prefabIndex != 603) { return prefabIndex == 666; } return true; } private static bool IsLegacyBigOar(ShipItem item) { if ((Object)(object)item != (Object)null && GetPrefabIndex(item) == 169) { return (Object)(object)((Component)item).GetComponent<ScaledOarController>() != (Object)null; } return false; } } internal sealed class ScaledOarDefinition { internal int PrefabIndex { get; } internal string ItemName { get; } internal float Scale { get; } internal float WaterPosDistance { get; } internal float WaterPosHeight { get; } internal float RowDipHeight { get; } internal float MassMultiplier { get; } internal int ValueMultiplier { get; } internal GameObject Prefab { get; set; } internal bool CacheValidationLogged { get; set; } internal ScaledOarDefinition(int prefabIndex, string itemName, float scale, float waterPosDistance, float waterPosHeight, float rowDipHeight, float massMultiplier, int valueMultiplier) { PrefabIndex = prefabIndex; ItemName = itemName; Scale = scale; WaterPosDistance = waterPosDistance; WaterPosHeight = waterPosHeight; RowDipHeight = rowDipHeight; MassMultiplier = massMultiplier; ValueMultiplier = valueMultiplier; } } internal static class ScaledOarFactory { internal const int VanillaOarPrefabIndex = 168; internal const int LegacyBigOarPrefabIndex = 169; internal const int BigOarPrefabIndex = 602; internal const int HugeOarPrefabIndex = 603; internal const int Bfo5000PrefabIndex = 666; internal const float BigOarScale = 2f; internal const float HugeOarScale = 3f; internal const float Bfo5000Scale = 5f; private static readonly ScaledOarDefinition[] Definitions = new ScaledOarDefinition[3] { new ScaledOarDefinition(602, "Big Oar", 2f, 1.5f, 2.8f, 1f, 8f, 4), new ScaledOarDefinition(603, "Huge Oar", 3f, 2.25f, 4.2f, 1.5f, 27f, 12), new ScaledOarDefinition(666, "BFO 5000", 5f, 3.75f, 7f, 2.5f, 125f, 10) }; private static readonly ScaledOarDefinition LegacyBigOarDefinition = new ScaledOarDefinition(169, "Big Oar", 2f, 1.5f, 2.8f, 1f, 8f, 4); internal static bool EnsureRegistered(PrefabsDirectory directory) { if ((Object)(object)directory == (Object)null || directory.directory == null) { ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogError((object)"Could not register scaled oars: PrefabsDirectory is unavailable."); } return false; } if (directory.directory.Length <= 168 || (Object)(object)directory.directory[168] == (Object)null) { ManualLogSource logSource2 = PowerfulOarPlugin.LogSource; if (logSource2 != null) { logSource2.LogError((object)("Could not register scaled oars: vanilla oar prefab " + $"{168} was not found.")); } return false; } ShipItemOar component = directory.directory[168].GetComponent<ShipItemOar>(); if ((Object)(object)component == (Object)null) { ManualLogSource logSource3 = PowerfulOarPlugin.LogSource; if (logSource3 != null) { logSource3.LogError((object)"Could not register scaled oars: prefab 168 is not a ShipItemOar."); } return false; } OarStats.Apply(component); EnsureDirectoryCapacity(directory); bool flag = true; ScaledOarDefinition[] definitions = Definitions; foreach (ScaledOarDefinition definition in definitions) { flag &= EnsureRegistered(directory, definition, component); } return flag & EnsureLegacyBigOarRegistered(directory, component); } internal static bool ValidateRuntimeCache(PrefabsDirectory directory) { if (!EnsureRegistered(directory)) { return false; } EnsureDirectoryCapacity(directory); EnsureShipItemCacheCapacity(directory); bool result = true; ScaledOarDefinition[] definitions = Definitions; foreach (ScaledOarDefinition scaledOarDefinition in definitions) { GameObject val = directory.directory[scaledOarDefinition.PrefabIndex]; ShipItem val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ShipItem>() : null); SaveablePrefab val3 = (((Object)(object)val != (Object)null) ? val.GetComponent<SaveablePrefab>() : null); ScaledOarController scaledOarController = (((Object)(object)val != (Object)null) ? val.GetComponent<ScaledOarController>() : null); if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)scaledOarController == (Object)null || val3.prefabIndex != scaledOarDefinition.PrefabIndex || scaledOarController.PrefabIndex != scaledOarDefinition.PrefabIndex) { ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogError((object)(scaledOarDefinition.ItemName + " registration failed validation: directory entry is missing ShipItem, ScaledOarController, or the expected prefab index.")); } result = false; continue; } directory.shipItems[scaledOarDefinition.PrefabIndex] = val2; if (!scaledOarDefinition.CacheValidationLogged) { scaledOarDefinition.CacheValidationLogged = true; ManualLogSource logSource2 = PowerfulOarPlugin.LogSource; if (logSource2 != null) { logSource2.LogInfo((object)("Validated " + scaledOarDefinition.ItemName + " prefab and item cache at index " + $"{scaledOarDefinition.PrefabIndex}.")); } } } GameObject val4 = directory.directory[169]; ShipItem val5 = (((Object)(object)val4 != (Object)null) ? val4.GetComponent<ShipItem>() : null); SaveablePrefab val6 = (((Object)(object)val4 != (Object)null) ? val4.GetComponent<SaveablePrefab>() : null); ScaledOarController scaledOarController2 = (((Object)(object)val4 != (Object)null) ? val4.GetComponent<ScaledOarController>() : null); if ((Object)(object)val5 == (Object)null || (Object)(object)val6 == (Object)null || (Object)(object)scaledOarController2 == (Object)null || val6.prefabIndex != 169 || scaledOarController2.PrefabIndex != 169) { ManualLogSource logSource3 = PowerfulOarPlugin.LogSource; if (logSource3 != null) { logSource3.LogError((object)("Legacy Big Oar compatibility failed validation at prefab index " + $"{169}.")); } result = false; } else { directory.shipItems[169] = val5; } return result; } internal static bool MigrateLegacyBigOar(SaveablePrefab saveable, SavePrefabData data) { if ((Object)(object)saveable == (Object)null || data == null || data.prefabIndex != 169) { return false; } ScaledOarController component = ((Component)saveable).GetComponent<ScaledOarController>(); ShipItemOar component2 = ((Component)saveable).GetComponent<ShipItemOar>(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || saveable.prefabIndex != 169) { return false; } saveable.prefabIndex = 602; component.Initialize(602, 2f); OarStats.Apply(component2); ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogInfo((object)("Migrated saved Big Oar from legacy prefab " + $"{169} to {602}; " + "the new index will be written on the next save.")); } return true; } private static bool EnsureLegacyBigOarRegistered(PrefabsDirectory directory, ShipItemOar vanillaOar) { GameObject val = directory.directory[169]; if ((Object)(object)val != (Object)null) { ScaledOarController component = val.GetComponent<ScaledOarController>(); SaveablePrefab component2 = val.GetComponent<SaveablePrefab>(); ShipItemOar component3 = val.GetComponent<ShipItemOar>(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null && (Object)(object)component3 != (Object)null && component.PrefabIndex == 169 && component2.prefabIndex == 169) { ConfigureScaledOar(val, component3, vanillaOar, LegacyBigOarDefinition); component.Initialize(169, 2f); return true; } ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogError((object)("Could not reserve legacy Big Oar prefab index " + $"{169}: it is already occupied by " + "'" + ((Object)val).name + "'. Old PowerfulOar saves using that index cannot be migrated safely.")); } return false; } GameObject val2 = directory.directory[602]; if ((Object)(object)(((Object)(object)val2 != (Object)null) ? val2.GetComponent<ShipItemOar>() : null) == (Object)null) { ManualLogSource logSource2 = PowerfulOarPlugin.LogSource; if (logSource2 != null) { logSource2.LogError((object)("Could not create legacy Big Oar compatibility prefab: " + $"current prefab {602} is unavailable.")); } return false; } GameObject val3 = null; try { val3 = Object.Instantiate<GameObject>(val2); ShipItemOar component4 = val3.GetComponent<ShipItemOar>(); ScaledOarController component5 = val3.GetComponent<ScaledOarController>(); if ((Object)(object)component4 == (Object)null || (Object)(object)component5 == (Object)null) { ManualLogSource logSource3 = PowerfulOarPlugin.LogSource; if (logSource3 != null) { logSource3.LogError((object)"Could not create legacy Big Oar compatibility prefab: required components are missing."); } Object.Destroy((Object)(object)val3); return false; } ConfigureScaledOar(val3, component4, vanillaOar, LegacyBigOarDefinition); component5.Initialize(169, 2f); directory.directory[169] = val3; ManualLogSource logSource4 = PowerfulOarPlugin.LogSource; if (logSource4 != null) { logSource4.LogInfo((object)($"Reserved prefab {169} for legacy " + $"Big Oar saves; new Big Oars use prefab {602}.")); } return true; } catch (Exception ex) { if ((Object)(object)val3 != (Object)null) { Object.Destroy((Object)(object)val3); } ManualLogSource logSource5 = PowerfulOarPlugin.LogSource; if (logSource5 != null) { logSource5.LogError((object)("Could not create legacy Big Oar compatibility prefab: " + ex)); } return false; } } private static bool EnsureRegistered(PrefabsDirectory directory, ScaledOarDefinition definition, ShipItemOar vanillaOar) { GameObject val = directory.directory[definition.PrefabIndex]; if ((Object)(object)val != (Object)null) { ScaledOarController scaledOarController = val.GetComponent<ScaledOarController>(); if ((Object)(object)val == (Object)(object)definition.Prefab || ((Object)(object)scaledOarController != (Object)null && scaledOarController.PrefabIndex == definition.PrefabIndex)) { ShipItemOar component = val.GetComponent<ShipItemOar>(); if ((Object)(object)component == (Object)null) { ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogError((object)("Could not configure " + definition.ItemName + ": ShipItemOar is missing.")); } return false; } if ((Object)(object)scaledOarController == (Object)null) { scaledOarController = val.AddComponent<ScaledOarController>(); } ConfigureScaledOar(val, component, vanillaOar, definition); definition.Prefab = val; scaledOarController.Initialize(definition.PrefabIndex, definition.Scale); return true; } ManualLogSource logSource2 = PowerfulOarPlugin.LogSource; if (logSource2 != null) { logSource2.LogError((object)("Could not register " + definition.ItemName + ": prefab index " + $"{definition.PrefabIndex} is already occupied by '{((Object)val).name}'.")); } return false; } if ((Object)(object)definition.Prefab != (Object)null) { ShipItemOar component2 = definition.Prefab.GetComponent<ShipItemOar>(); ScaledOarController component3 = definition.Prefab.GetComponent<ScaledOarController>(); if ((Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null) { ManualLogSource logSource3 = PowerfulOarPlugin.LogSource; if (logSource3 != null) { logSource3.LogError((object)("Could not restore " + definition.ItemName + ": cached components are missing.")); } return false; } ConfigureScaledOar(definition.Prefab, component2, vanillaOar, definition); component3.Initialize(definition.PrefabIndex, definition.Scale); directory.directory[definition.PrefabIndex] = definition.Prefab; return true; } GameObject val2 = null; try { val2 = Object.Instantiate<GameObject>(directory.directory[168]); SaveablePrefab component4 = val2.GetComponent<SaveablePrefab>(); ShipItemOar component5 = val2.GetComponent<ShipItemOar>(); if ((Object)(object)component4 == (Object)null || (Object)(object)component5 == (Object)null) { ManualLogSource logSource4 = PowerfulOarPlugin.LogSource; if (logSource4 != null) { logSource4.LogError((object)("Could not register " + definition.ItemName + ": the cloned vanilla prefab is missing SaveablePrefab or ShipItemOar.")); } Object.Destroy((Object)(object)val2); return false; } ConfigureScaledOar(val2, component5, vanillaOar, definition); ScaledOarController scaledOarController2 = val2.GetComponent<ScaledOarController>(); if ((Object)(object)scaledOarController2 == (Object)null) { scaledOarController2 = val2.AddComponent<ScaledOarController>(); } scaledOarController2.Initialize(definition.PrefabIndex, definition.Scale); directory.directory[definition.PrefabIndex] = val2; definition.Prefab = val2; ManualLogSource logSource5 = PowerfulOarPlugin.LogSource; if (logSource5 != null) { logSource5.LogInfo((object)("Registered " + definition.ItemName + " at prefab index " + $"{definition.PrefabIndex}. Scale={definition.Scale:0.0}x, " + $"mass={((ShipItem)component5).mass:0.0}, value={((ShipItem)component5).value}, " + $"water distance={definition.WaterPosDistance:0.00}, " + $"water height={definition.WaterPosHeight:0.00}, " + $"dip={definition.RowDipHeight:0.00}, big=false.")); } return true; } catch (Exception arg) { if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } ManualLogSource logSource6 = PowerfulOarPlugin.LogSource; if (logSource6 != null) { logSource6.LogError((object)$"Could not register {definition.ItemName}: {arg}"); } return false; } } private static void ConfigureScaledOar(GameObject prefab, ShipItemOar oar, ShipItemOar vanillaOar, ScaledOarDefinition definition) { //IL_0037: 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) SaveablePrefab component = prefab.GetComponent<SaveablePrefab>(); if ((Object)(object)component == (Object)null) { throw new InvalidOperationException(definition.ItemName + " is missing SaveablePrefab."); } ((Object)prefab).name = definition.ItemName; prefab.transform.localScale = Vector3.one * definition.Scale; Object.DontDestroyOnLoad((Object)(object)prefab); component.prefabIndex = definition.PrefabIndex; ((ShipItem)oar).name = definition.ItemName; ((PickupableItem)oar).big = false; ((ShipItem)oar).wallAttachment = false; ((ShipItem)oar).mass = ((ShipItem)vanillaOar).mass * definition.MassMultiplier; ((ShipItem)oar).value = ((ShipItem)vanillaOar).value * definition.ValueMultiplier; oar.waterPosDistance = definition.WaterPosDistance; oar.waterPosHeight = definition.WaterPosHeight; oar.rowDipHeight = definition.RowDipHeight; OarStats.Apply(oar); HookHangMoreCompatibility.Exclude((ShipItem)(object)oar); } private static void EnsureDirectoryCapacity(PrefabsDirectory directory) { if (directory.directory.Length <= 666) { Array.Resize(ref directory.directory, 667); } } private static void EnsureShipItemCacheCapacity(PrefabsDirectory directory) { if (directory.shipItems == null) { directory.shipItems = (ShipItem[])(object)new ShipItem[directory.directory.Length]; for (int i = 0; i < directory.directory.Length; i++) { GameObject val = directory.directory[i]; if ((Object)(object)val != (Object)null) { directory.shipItems[i] = val.GetComponent<ShipItem>(); } } } else if (directory.shipItems.Length < directory.directory.Length) { Array.Resize(ref directory.shipItems, directory.directory.Length); } } } [DefaultExecutionOrder(10000)] internal sealed class ScaledOarController : MonoBehaviour { private static readonly HashSet<ScaledOarController> ActiveControllers = new HashSet<ScaledOarController>(); private static readonly FieldInfo CollidedCollidersField = AccessTools.Field(typeof(PickupableItemCollisionChecker), "collidedCols"); private static readonly FieldInfo CurrentDecolDistanceField = AccessTools.Field(typeof(PickupableItemCollisionChecker), "currentDecolDistance"); [SerializeField] private int prefabIndex; [SerializeField] private float targetScale = 1f; private ShipItemOar item; private ItemRigidbody itemRigidbody; private Outline outline; private bool wasInSleepOrLoadTransition; private Coroutine initializationRoutine; private bool initializationGuardActive; private bool ownsKinematicGuard; private bool persistentKinematic; private bool waitingForSavedCrate; private bool waitingForSavedInventory; private int savedCrateId; internal int PrefabIndex => prefabIndex; internal void Initialize(int newPrefabIndex, float newTargetScale) { prefabIndex = newPrefabIndex; targetScale = newTargetScale; CacheItemComponents(); BeginPhysicsInitialization(); HookHangMoreCompatibility.Exclude((ShipItem)(object)item); } internal bool CanRestoreSavedCrate(int crateId) { if (waitingForSavedCrate && savedCrateId > 0) { return savedCrateId == crateId; } return false; } internal void PrepareForSavedState(SavePrefabData data) { //IL_009f: 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_00b9: Unknown result type (might be due to invalid IL or missing references) if (data == null) { return; } CacheItemComponents(); BeginPhysicsInitialization(); waitingForSavedCrate = data.crateId > 0; waitingForSavedInventory = !waitingForSavedCrate && data.inventorySlot > -1; savedCrateId = (waitingForSavedCrate ? data.crateId : 0); if (waitingForSavedCrate && !((Object)(object)item == (Object)null) && !((Object)(object)itemRigidbody == (Object)null)) { itemRigidbody.attached = true; itemRigidbody.disableCol = true; itemRigidbody.inStove = true; ((Component)this).transform.localScale = Vector3.one * ((ShipItem)item).inventoryScale * 0.33f; Collider component = ((Component)item).GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { component.enabled = false; } } } internal void CompleteSavedCrateRestore(int crateId) { if (CanRestoreSavedCrate(crateId)) { waitingForSavedCrate = false; savedCrateId = 0; } } internal void OnEnteredInventory() { waitingForSavedInventory = false; } internal void RestoreWorldScaleAfterStorage() { waitingForSavedCrate = false; waitingForSavedInventory = false; savedCrateId = 0; CacheItemComponents(); Collider val = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<Collider>() : null); if ((Object)(object)val != (Object)null) { val.enabled = true; } BeginPhysicsInitialization(); } internal void SetPersistentKinematic(bool state) { //IL_0061: 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) persistentKinematic = state; CacheItemComponents(); if ((Object)(object)itemRigidbody == (Object)null) { return; } if (state) { itemRigidbody.debugForceKinematic = true; } else if (!initializationGuardActive) { itemRigidbody.debugForceKinematic = false; } Rigidbody body = itemRigidbody.GetBody(); if ((Object)(object)body != (Object)null) { if (state) { body.isKinematic = true; body.velocity = Vector3.zero; body.angularVelocity = Vector3.zero; } body.useGravity = !state; } } internal static void SuppressTransitionOutlines() { foreach (ScaledOarController activeController in ActiveControllers) { if ((Object)(object)activeController != (Object)null) { activeController.SuppressStaleOutline(); } } } private void Awake() { CacheItemComponents(); BeginPhysicsInitialization(); HookHangMoreCompatibility.Exclude((ShipItem)(object)item); } private void OnEnable() { ActiveControllers.Add(this); StartInitializationRoutineIfNeeded(); } private void OnDisable() { ActiveControllers.Remove(this); if (initializationRoutine != null) { ((MonoBehaviour)this).StopCoroutine(initializationRoutine); initializationRoutine = null; } } private void OnDestroy() { ActiveControllers.Remove(this); } private void LateUpdate() { CacheItemComponents(); if ((Object)(object)item == (Object)null) { return; } bool flag = GameState.sleeping || GameState.recovering || GameState.currentlyLoading || GameState.justWokeUp; if (flag) { if (!GameState.sleeping && !GameState.currentlyLoading) { ReconcileCollisionState(); } SuppressStaleOutline(); } else if (wasInSleepOrLoadTransition) { ReconcileCollisionState(); SuppressStaleOutline(); } wasInSleepOrLoadTransition = flag; } private void ApplyScale(Transform target) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.one * targetScale; if (target.localScale != val) { target.localScale = val; } } private void CacheItemComponents() { if ((Object)(object)item == (Object)null) { item = ((Component)this).GetComponent<ShipItemOar>(); } if ((Object)(object)itemRigidbody == (Object)null && (Object)(object)item != (Object)null) { itemRigidbody = ((ShipItem)item).itemRigidbodyC; } } private void BeginPhysicsInitialization() { CacheItemComponents(); if ((Object)(object)item == (Object)null || (Object)(object)itemRigidbody == (Object)null) { return; } ApplyScale(((Component)this).transform); ApplyScale(((Component)itemRigidbody).transform); if (!initializationGuardActive) { initializationGuardActive = true; if (!itemRigidbody.debugForceKinematic) { itemRigidbody.debugForceKinematic = true; ownsKinematicGuard = true; } } StartInitializationRoutineIfNeeded(); } private void StartInitializationRoutineIfNeeded() { if (initializationGuardActive && initializationRoutine == null && ((Behaviour)this).isActiveAndEnabled && ((Component)this).gameObject.activeInHierarchy) { initializationRoutine = ((MonoBehaviour)this).StartCoroutine(CompletePhysicsInitialization()); } } private IEnumerator CompletePhysicsInitialization() { while ((Object)(object)itemRigidbody == (Object)null || (Object)(object)itemRigidbody.GetBody() == (Object)null || (Object)(object)((Component)itemRigidbody).GetComponent<Collider>() == (Object)null) { CacheItemComponents(); yield return null; } int storageRestoreGraceFrames = 0; while (GameState.currentlyLoading || GameState.loadingBoatLocalItems || GameState.recovering || waitingForSavedCrate || waitingForSavedInventory) { if (!GameState.currentlyLoading && !GameState.loadingBoatLocalItems && !GameState.recovering && (waitingForSavedCrate || waitingForSavedInventory)) { storageRestoreGraceFrames++; if (storageRestoreGraceFrames > 30) { RecoverFailedStorageRestore(); } } else { storageRestoreGraceFrames = 0; } yield return null; } Rigidbody body = itemRigidbody.GetBody(); if ((Object)(object)body != (Object)null) { body.isKinematic = true; body.velocity = Vector3.zero; body.angularVelocity = Vector3.zero; if (persistentKinematic) { body.useGravity = false; } } Physics.SyncTransforms(); yield return (object)new WaitForFixedUpdate(); ReleaseInitializationGuard(); } private void RecoverFailedStorageRestore() { bool num = waitingForSavedCrate; waitingForSavedCrate = false; waitingForSavedInventory = false; savedCrateId = 0; SaveablePrefab val = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<SaveablePrefab>() : null); if (num && (Object)(object)val != (Object)null) { val.currentCrateId = 0; } if ((Object)(object)itemRigidbody != (Object)null) { itemRigidbody.attached = false; itemRigidbody.disableCol = false; itemRigidbody.inStove = false; } Collider val2 = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<Collider>() : null); if ((Object)(object)val2 != (Object)null) { val2.enabled = true; } ApplyScale(((Component)this).transform); if ((Object)(object)itemRigidbody != (Object)null) { ApplyScale(((Component)itemRigidbody).transform); } ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogWarning((object)("Recovered " + (((ShipItem)(item?)).name ?? "scaled oar") + " after its saved inventory or crate location could not be restored.")); } } private void ReleaseInitializationGuard() { initializationRoutine = null; initializationGuardActive = false; if (ownsKinematicGuard && !persistentKinematic && (Object)(object)itemRigidbody != (Object)null) { itemRigidbody.debugForceKinematic = false; } ownsKinematicGuard = false; } private void SuppressStaleOutline() { if ((Object)(object)item == (Object)null) { item = ((Component)this).GetComponent<ShipItemOar>(); } if ((Object)(object)item != (Object)null) { ((GoPointerButton)item).enableRedOutline = false; } if ((Object)(object)outline == (Object)null) { outline = ((Component)this).GetComponent<Outline>(); } if ((Object)(object)outline != (Object)null) { ((Behaviour)outline).enabled = false; } } private void ReconcileCollisionState() { //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) PickupableItemCollisionChecker val = ((PickupableItem)(item?)).colChecker; if ((Object)(object)val == (Object)null || CollidedCollidersField == null || CurrentDecolDistanceField == null) { return; } List<Collider> list = CollidedCollidersField.GetValue(val) as List<Collider>; Collider component = ((Component)val).GetComponent<Collider>(); int num = 0; float num2 = 0f; if (Object.op_Implicit((Object)(object)((PickupableItem)item).held) && ((ShipItem)item).GetCurrentInventorySlot() < 0 && (Object)(object)component != (Object)null && component.enabled && list != null) { Vector3 val2 = default(Vector3); float num3 = default(float); foreach (Collider item in list) { if (!((Object)(object)item == (Object)null) && item.enabled && ((Component)item).gameObject.activeInHierarchy && !item.isTrigger && !((Object)(object)((Component)item).gameObject == (Object)(object)((Component)this.item).gameObject) && !((Component)item).CompareTag("Boat") && Physics.ComputePenetration(component, ((Component)component).transform.position, ((Component)component).transform.rotation, item, ((Component)item).transform.position, ((Component)item).transform.rotation, ref val2, ref num3) && num3 > 0f) { num++; num2 = Mathf.Max(num2, num3); } } } val.collisions = num; CurrentDecolDistanceField.SetValue(val, num2); val.allowObstructedDropping = num2 < 0.06f; ((GoPointerButton)this.item).enableRedOutline = false; } } [HarmonyPatch(typeof(PrefabsDirectory), "Start")] internal static class ScaledOarPrefabRegistrationPatch { [HarmonyPrefix] [HarmonyPriority(0)] private static void Prefix(PrefabsDirectory __instance) { ScaledOarFactory.EnsureRegistered(__instance); } [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(PrefabsDirectory __instance) { ScaledOarFactory.ValidateRuntimeCache(__instance); BoneIslandBfoPlacement.OnPrefabsReady(); } } [HarmonyPatch(typeof(OutlineEffect), "OnEnable")] internal static class ScaledOarOutlineEffectPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix() { ScaledOarController.SuppressTransitionOutlines(); } } [HarmonyPatch(typeof(ShipItemHammer), "CanNail")] internal static class ScaledOarNailingPatch { [HarmonyPostfix] private static void Postfix(ShipItem item, ref bool __result) { if (HookHangMoreCompatibility.IsExcluded(item)) { __result = item.sold; } } } [HarmonyPatch(typeof(ShipItem), "Awake")] [HarmonyAfter(new string[] { "com.raddude.hookshangmore" })] internal static class HookHangMoreExclusionPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(ShipItem __instance) { HookHangMoreCompatibility.Exclude(__instance); } } [HarmonyPatch(typeof(ItemRigidbody), "LateUpdate")] internal static class ScaledOarRigidbodyScalePatch { [HarmonyPrefix] private static bool Prefix(ItemRigidbody __instance) { if (!OarStats.IsScaledOar(__instance.GetShipItem())) { return true; } return (Object)(object)__instance.GetCurrentInventorySlot() != (Object)null; } } [HarmonyPatch(typeof(SaveablePrefab), "Load")] internal static class ScaledOarSavedStatePatch { [HarmonyPostfix] private static void Postfix(SaveablePrefab __instance, SavePrefabData data) { ScaledOarFactory.MigrateLegacyBigOar(__instance, data); ((Component)__instance).GetComponent<ScaledOarController>()?.PrepareForSavedState(data); } } [HarmonyPatch(typeof(ItemRigidbody), "EnterInventorySlot")] internal static class ScaledOarInventoryEnterPatch { [HarmonyPostfix] private static void Postfix(ItemRigidbody __instance) { ShipItem shipItem = __instance.GetShipItem(); if (shipItem != null) { ((Component)shipItem).GetComponent<ScaledOarController>()?.OnEnteredInventory(); } } } [HarmonyPatch(typeof(ItemRigidbody), "ExitInventorySlot")] internal static class ScaledOarInventoryExitPatch { [HarmonyPostfix] private static void Postfix(ItemRigidbody __instance) { ShipItem shipItem = __instance.GetShipItem(); if (shipItem != null) { ((Component)shipItem).GetComponent<ScaledOarController>()?.RestoreWorldScaleAfterStorage(); } } } [HarmonyPatch(typeof(CrateInventory), "InsertItem")] internal static class ScaledOarCrateInsertPatch { [HarmonyPrefix] private static bool Prefix(CrateInventory __instance, ShipItem item) { if (!OarStats.IsScaledOar(item)) { return true; } SaveablePrefab component = ((Component)item).GetComponent<SaveablePrefab>(); SaveablePrefab component2 = ((Component)__instance).GetComponent<SaveablePrefab>(); int num = (((Object)(object)component2 != (Object)null) ? component2.instanceId : 0); ScaledOarController component3 = ((Component)item).GetComponent<ScaledOarController>(); if (num > 0 && __instance.containedItems.Contains(item)) { if ((Object)(object)component != (Object)null) { component.currentCrateId = num; } component3?.CompleteSavedCrateRestore(num); return false; } bool num2; if (!((Object)(object)component3 != (Object)null)) { if (num <= 0 || !((Object)(object)component != (Object)null)) { goto IL_009c; } num2 = component.currentCrateId == num; } else { num2 = component3.CanRestoreSavedCrate(num); } if (num2) { component3?.CompleteSavedCrateRestore(num); return true; } goto IL_009c; IL_009c: if ((Object)(object)component != (Object)null && component.currentCrateId == num) { component.currentCrateId = 0; } return false; } } [HarmonyPatch(typeof(CrateInventory), "WithdrawItem")] internal static class ScaledOarCrateWithdrawPatch { [HarmonyPostfix] private static void Postfix(ShipItem item) { if (item != null) { ((Component)item).GetComponent<ScaledOarController>()?.RestoreWorldScaleAfterStorage(); } } } [HarmonyPatch(typeof(CrateInventoryButton), "OnActivate")] internal static class ScaledOarCrateUiPatch { [HarmonyPrefix] private static bool Prefix(GoPointer activatingPointer) { PickupableItem val = (((Object)(object)activatingPointer != (Object)null) ? activatingPointer.GetHeldItem() : null); if (!OarStats.IsScaledOar(((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<ShipItem>() : null)) { return true; } if ((Object)(object)NotificationUi.instance != (Object)null) { NotificationUi.instance.ShowNotification("Scaled oars cannot be stored in crates."); } CrateInventoryUI instance = CrateInventoryUI.instance; if (instance != null) { instance.RefreshButtons(); } return false; } } [HarmonyPatch(typeof(ShopItemSpawner), "Start")] internal static class BigOarVendorPatch { private sealed class VendorPlacement { internal readonly string SpawnerName; internal readonly Vector3 LocalPosition; internal readonly Vector3 LocalEuler; internal VendorPlacement(string spawnerName, Vector3 localPosition, Vector3 localEuler) { //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_0015: 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) SpawnerName = spawnerName; LocalPosition = localPosition; LocalEuler = localEuler; } } private static readonly Dictionary<string, VendorPlacement> TargetPlacements = new Dictionary<string, VendorPlacement> { { "island 9 E Dragon Cliffs", new VendorPlacement("shop item spawner (236)", new Vector3(0.198f, 1.5f, -0.049f), new Vector3(0.625f, -176.864f, 0.7f)) }, { "island 1 A Gold Rock", new VendorPlacement("shop item (224)", new Vector3(0.145f, 1.467f, -0.004f), new Vector3(0f, -12.273f, 0f)) }, { "island 15 M (Fort)", new VendorPlacement("shop item (284)", new Vector3(0.287f, 1.46f, -0.251f), new Vector3(-2.876f, -2.876f, -1.02f)) } }; [HarmonyPrefix] [HarmonyPriority(0)] private static void Prefix(ShopItemSpawner __instance) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) Scene scene = ((Component)__instance).gameObject.scene; if (!((Scene)(ref scene)).IsValid() || !TargetPlacements.TryGetValue(((Scene)(ref scene)).name, out var value) || ((Object)((Component)__instance).gameObject).name != value.SpawnerName) { return; } PrefabsDirectory instance = PrefabsDirectory.instance; if ((Object)(object)instance == (Object)null || !ScaledOarFactory.ValidateRuntimeCache(instance)) { ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogError((object)("Could not add Big Oar to vendor in " + ((Scene)(ref scene)).name + ": prefab directory unavailable.")); } return; } int prefabIndex = OarStats.GetPrefabIndex(((Object)(object)__instance.itemPrefab != (Object)null) ? __instance.itemPrefab.GetComponent<ShipItem>() : null); switch (prefabIndex) { case 602: break; default: { ManualLogSource logSource3 = PowerfulOarPlugin.LogSource; if (logSource3 != null) { logSource3.LogWarning((object)("Configured Big Oar vendor slot '" + value.SpawnerName + "' in " + ((Scene)(ref scene)).name + " does not contain vanilla oar prefab " + $"{168}; found {prefabIndex}.")); } break; } case 168: { __instance.itemPrefab = instance.directory[602]; ScaledOarVendorDisplaySpawner scaledOarVendorDisplaySpawner = ((Component)__instance).GetComponent<ScaledOarVendorDisplaySpawner>(); if ((Object)(object)scaledOarVendorDisplaySpawner == (Object)null) { scaledOarVendorDisplaySpawner = ((Component)__instance).gameObject.AddComponent<ScaledOarVendorDisplaySpawner>(); } scaledOarVendorDisplaySpawner.Initialize(((Scene)(ref scene)).name, "Big Oar", 602, value.LocalPosition, value.LocalEuler, 2f); ManualLogSource logSource2 = PowerfulOarPlugin.LogSource; if (logSource2 != null) { logSource2.LogInfo((object)("Replaced one vanilla-oar vendor slot with Big Oar in " + ((Scene)(ref scene)).name + " at '" + value.SpawnerName + "' using its configured local pose.")); } break; } } } } [HarmonyPatch(typeof(Shopkeeper), "Start")] internal static class HugeOarVendorPatch { internal const string SceneName = "island 27 Lagoon SwampShipyard"; internal const string ShopkeeperName = "shopkeeper (16)"; internal const string NpcName = "Modular NPC"; [HarmonyPostfix] private static void Postfix(Shopkeeper __instance) { if (IsTarget(__instance)) { HugeOarVendorInstaller hugeOarVendorInstaller = ((Component)__instance).GetComponent<HugeOarVendorInstaller>(); if ((Object)(object)hugeOarVendorInstaller == (Object)null) { hugeOarVendorInstaller = ((Component)__instance).gameObject.AddComponent<HugeOarVendorInstaller>(); } hugeOarVendorInstaller.Initialize(__instance); } } internal static bool IsTarget(Shopkeeper shopkeeper) { //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 ((Object)(object)shopkeeper == (Object)null || ((Object)((Component)shopkeeper).gameObject).name != "shopkeeper (16)") { return false; } Scene scene = ((Component)shopkeeper).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { return ((Scene)(ref scene)).name == "island 27 Lagoon SwampShipyard"; } return false; } } internal sealed class HugeOarVendorInstaller : MonoBehaviour { private const string SpawnerName = "PowerfulOar Huge Oar shop spawner"; private static readonly Vector3 LocalPosition = new Vector3(-1.444f, 4.292f, 0.854f); private static readonly Vector3 LocalEuler = new Vector3(8.857f, -110.947f, 1.63f); private Shopkeeper shopkeeper; private HugeOarPurchaseDialogueArea dialogueArea; private float nextAttempt; private bool complete; private bool reportedMissingNpc; internal void Initialize(Shopkeeper newShopkeeper) { shopkeeper = newShopkeeper; nextAttempt = 0f; } internal void ShowPurchaseReaction(int purchaseCount) { if ((Object)(object)dialogueArea != (Object)null) { dialogueArea.ShowPurchase(HugeOarPurchaseState.GetDialogue(purchaseCount)); } } private void Update() { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) if (complete || Time.unscaledTime < nextAttempt) { return; } if ((Object)(object)shopkeeper == (Object)null) { ((Behaviour)this).enabled = false; return; } nextAttempt = Time.unscaledTime + 1f; Transform val = ((Component)shopkeeper).transform.Find("Modular NPC"); if ((Object)(object)val == (Object)null) { if (!reportedMissingNpc) { reportedMissingNpc = true; ManualLogSource logSource = PowerfulOarPlugin.LogSource; if (logSource != null) { logSource.LogError((object)"Could not add Huge Oar to Kicia Bay: shopkeeper (16)/Modular NPC was not found; retrying."); } } nextAttempt = Time.unscaledTime + 5f; return; } PrefabsDirectory instance = PrefabsDirectory.instance; if ((Object)(object)instance == (Object)null) { return; } if (!ScaledOarFactory.ValidateRuntimeCache(instance)) { ManualLogSource logSource2 = PowerfulOarPlugin.LogSource; if (logSource2 != null) { logSource2.LogError((object)"Could not add Huge Oar to Kicia Bay: scaled-oar prefab validation failed."); } ((Behaviour)this).enabled = false; return; } if ((Object)(object)val.Find("PowerfulOar Huge Oar shop spawner") != (Object)null) { ManualLogSource logSource3 = PowerfulOarPlugin.LogSource; if (logSource3 != null) { logSource3.LogWarning((object)"Skipped duplicate Kicia Bay Huge Oar shop spawner."); } complete = true; ((Behaviour)this).enabled = false; return; } GameObject val2 = null; try { val2 = new GameObject("PowerfulOar Huge Oar shop spawner"); val2.SetActive(false); val2.transform.SetParent(val, false); val2.transform.localPosition = LocalPosition; val2.transform.localRotation = Quaternion.Euler(LocalEuler); val2.transform.localScale = Vector3.one; ShopItemSpawner obj = val2.AddComponent<ShopItemSpawner>(); obj.itemPrefab = instance.directory[603]; obj.availableAtNight = false; obj.priceMult = 1f; val2.AddComponent<ScaledOarVendorDisplaySpawner>().Initialize("island 27 Lagoon SwampShipyard", "Huge Oar", 603, Vector3.zero, Vector3.zero, 3f); dialogueArea = HugeOarPurchaseDialogueArea.Create(val); val2.SetActive(true); complete = true; ((Behaviour)this).enabled = false; ManualLogSource logSource4 = PowerfulOarPlugin.LogSource; if (logSource4 != null) { logSource4.LogInfo((object)("Added Huge Oar prefab 603 beneath Kicia Bay shopkeeper (16)/Modular NPC at local position " + ((object)LocalPosition/*cast due to .constrained prefix*/).ToString() + " and local rotation " + ((object)LocalEuler/*cast due to .constrained prefix*/).ToString() + ".")); } } catch (Exception ex) { if ((Object)(object)dialogueArea != (Object)null) { Object.Destroy((Object)(object)((Component)dialogueArea).gameObject); dialogueArea = null; } if ((Object)(object)val2 != (Object)null) { Object.Destroy((Object)(object)val2); } nextAttempt = Time.unscaledTime + 10f; ManualLogSource logSource5 = PowerfulOarPlugin.LogSource; if (logSource5 != null) { logSource5.LogError((object)("Could not install the Kicia Bay Huge Oar vendor; retrying: " + ex)); } } } } [HarmonyPatch(typeof(ShopItemSpawner), "SpawnItem")] internal static class ScaledOarVendorSpawnPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(ShopItemSpawner __instance, ShipItem ___item) { ScaledOarVendorDisplaySpawner component = ((Component)__instance).GetComponent<ScaledOarVendorDisplaySpawner>(); if ((Object)(object)component != (Object)null) { component.ConfigureSpawnedItem(___item); } } } internal sealed class ScaledOarVendorDisplaySpawner : MonoBehaviour { private string sceneName; private string itemName; private int prefabIndex; private Vector3 localPosition; private Quaternion localRotation; private float targetWorldScale; internal void Initialize(string newSceneName, string newItemName, int newPrefabIndex, Vector3 newLocalPosition, Vector3 newLocalEuler, float newTargetWorldScale) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) sceneName = newSceneName; itemName = newItemName; prefabIndex = newPrefabIndex; localPosition = newLocalPosition; localRotation = Quaternion.Euler(newLocalEuler); targetWorldScale = newTargetWorldScale; } internal void ConfigureSpawnedItem(ShipItem item) { //IL_0037: 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) if