using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
internal sealed class ConfigurationManagerAttributes
{
public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput);
public bool? ShowRangeAsPercent;
public Action<ConfigEntryBase> CustomDrawer;
public CustomHotkeyDrawerFunc CustomHotkeyDrawer;
public bool? Browsable;
public string Category;
public object DefaultValue;
public bool? HideDefaultButton;
public bool? HideSettingName;
public string Description;
public string DispName;
public int? Order;
public bool? ReadOnly;
public bool? IsAdvanced;
public Func<object, string> ObjToStr;
public Func<string, object> StrToObj;
}
namespace TowableBoats;
internal class AssetTools
{
public static AssetBundle bundle;
private const string assetDir = "TowableBoats";
private const string assetFile = "towable_boats.assets";
public static void LoadAssetBundles()
{
string text = Path.Combine(Paths.PluginPath, "TowableBoats", "towable_boats.assets");
string text2 = Path.Combine(Paths.PluginPath, "towable_boats.assets");
bundle = AssetBundle.LoadFromFile(File.Exists(text) ? text : text2);
if ((Object)(object)bundle == (Object)null)
{
Debug.LogError((object)"Bundle not loaded! Did you place it in the correct folder?");
}
else
{
Debug.Log((object)("TowableBoats: loaded bundle " + ((object)bundle).ToString()));
}
}
}
internal class BoatPerformancePatches
{
[HarmonyPatch(typeof(BoatHorizon))]
private static class BoatHorizonPatch
{
[HarmonyPatch("UpdateKinematic")]
[HarmonyPostfix]
public static void BoatKinematicPatch(BoatHorizon __instance, ref Rigidbody ___rigidbody)
{
if (___rigidbody.isKinematic && GameState.sleeping)
{
TowingSet componentInParent = ((Component)__instance).GetComponentInParent<TowingSet>();
if (componentInParent != null)
{
___rigidbody.isKinematic = !componentInParent.PhysicsMode();
}
}
}
}
[HarmonyPatch(typeof(BoatPerformanceSwitcher))]
private static class BoatPerformanceSwitcherPatch
{
[HarmonyPatch("Update")]
[HarmonyPrefix]
public static bool BoatPerformaceSwitcherPatch(BoatPerformanceSwitcher __instance, ref Rigidbody ___body, BoatDamage ___damage)
{
if ((Object)(object)GameState.lastBoat == (Object)(object)((Component)__instance).transform || ___damage.sunk)
{
return true;
}
TowingSet componentInParent = ((Component)__instance).GetComponentInParent<TowingSet>();
if (componentInParent != null)
{
Util.InvokePrivate(__instance, "SetPerformanceMode", !componentInParent.PhysicsMode());
return false;
}
return true;
}
}
}
[StructLayout(LayoutKind.Sequential, Size = 1)]
public readonly struct CleatDefs
{
public static readonly Array[] brig = new Array[6]
{
new object[4]
{
"cleat_stern_left",
(object)new Vector3(-14.9f, 4.36f, 2.23f),
(object)new Quaternion(0.7071068f, 0f, 0f, 0.7071068f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_stern_right",
(object)new Vector3(-14.9f, 4.36f, -2.23f),
(object)new Quaternion(0.7071068f, 0f, 0f, 0.7071068f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_mid_aft_left",
(object)new Vector3(-2.3f, 3.53f, 3.27f),
(object)new Quaternion(-0.7058f, 0.0252f, -0.0246f, 0.7075f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_mid_aft_right",
(object)new Vector3(-2.3f, 3.53f, -3.27f),
(object)new Quaternion(-0.7058f, 0.0252f, -0.0246f, 0.7075f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_mid_fore_left",
(object)new Vector3(4.85f, 3.57f, 3.02f),
(object)new Quaternion(-0.7041f, 0.0292f, 0.0692f, 0.7061f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_mid_fore_right",
(object)new Vector3(4.85f, 3.57f, -3.02f),
(object)new Quaternion(-0.7036f, -0.0384f, 0.0012f, 0.7095f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
}
};
public static readonly Array[] sanbuq = new Array[6]
{
new object[4]
{
"cleat_stern_left",
(object)new Vector3(-12.08f, 2.12f, 1.48f),
(object)new Quaternion(0.4912f, -0.5087f, -0.5087f, -0.4912f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_stern_right",
(object)new Vector3(-12.08f, 2.12f, -1.48f),
(object)new Quaternion(0.5087f, -0.4912f, -0.4912f, -0.5087f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_mid_aft_left",
(object)new Vector3(-1.4f, 2.12f, 2.46f),
(object)new Quaternion(0.7071068f, 0f, 0f, -0.7071068f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_mid_aft_right",
(object)new Vector3(-1.4f, 2.12f, -2.46f),
(object)new Quaternion(0.7071068f, 0f, 0f, -0.7071068f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_mid_fore_left",
(object)new Vector3(4.2f, 2.32f, 2.25f),
(object)new Quaternion(-0.7071f, 0f, 0.0371f, 0.7061f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_mid_fore_right",
(object)new Vector3(4.2f, 2.32f, -2.25f),
(object)new Quaternion(-0.7058f, -0.0432f, 0.0062f, 0.7071f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
}
};
public static readonly Array[] junk = new Array[6]
{
new object[4]
{
"cleat_stern_left",
(object)new Vector3(-9.7f, 2.27f, 0.8f),
(object)new Quaternion(0.4731f, -0.5255f, -0.5255f, -0.4731f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_stern_right",
(object)new Vector3(-9.7f, 2.27f, -0.8f),
(object)new Quaternion(0.5255f, -0.4731f, -0.4731f, -0.5255f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_mid_aft_left",
(object)new Vector3(1.24f, 1.01f, 2.52f),
(object)new Quaternion(0.7071068f, 0f, 0f, -0.7071068f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_mid_aft_right",
(object)new Vector3(1.24f, 1.01f, -2.52f),
(object)new Quaternion(0.7071068f, 0f, 0f, -0.7071068f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_mid_fore_left",
(object)new Vector3(7.68f, 1.1f, 2.02f),
(object)new Quaternion(-0.7071f, 0.0062f, 0.0309f, 0.7064f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
},
new object[4]
{
"cleat_mid_fore_right",
(object)new Vector3(7.68f, 1.1f, -2.02f),
(object)new Quaternion(-0.7064f, -0.0309f, -0.0061f, 0.7071f),
(object)new Vector3(0.6f, 0.6f, 0.6f)
}
};
public static readonly Array[] cog = new Array[2]
{
new object[4]
{
"cleat_stern_left",
(object)new Vector3(6.66f, 2.41f, 1.25f),
(object)new Quaternion(0.5f, -0.5f, -0.5f, -0.5f),
(object)new Vector3(0.5f, 0.5f, 0.5f)
},
new object[4]
{
"cleat_stern_right",
(object)new Vector3(6.66f, 2.41f, -1.25f),
(object)new Quaternion(0.5f, -0.5f, -0.5f, -0.5f),
(object)new Vector3(0.5f, 0.5f, 0.5f)
}
};
public static readonly Array[] dhow = new Array[2]
{
new object[4]
{
"cleat_stern_left",
(object)new Vector3(-6.4f, 1.815f, 1.53f),
(object)new Quaternion(-0.0616f, -0.7044f, -0.7044f, -0.0616f),
(object)new Vector3(0.5f, 0.5f, 0.5f)
},
new object[4]
{
"cleat_stern_right",
(object)new Vector3(-6.4f, 1.815f, -1.53f),
(object)new Quaternion(-0.0616f, -0.7044f, -0.7044f, -0.0616f),
(object)new Vector3(0.5f, 0.5f, 0.5f)
}
};
public static readonly Array[] kakam = new Array[2]
{
new object[4]
{
"cleat_stern_left",
(object)new Vector3(-6.3f, 2.86f, 0.64f),
(object)new Quaternion(0.6744f, 0.2126f, 0.2126f, -0.6744f),
(object)new Vector3(0.5f, 0.5f, 0.5f)
},
new object[4]
{
"cleat_stern_right",
(object)new Vector3(-6.3f, 2.86f, -0.64f),
(object)new Quaternion(0.6744f, -0.2126f, -0.2126f, -0.6744f),
(object)new Vector3(0.5f, 0.5f, 0.5f)
}
};
}
internal class MooringPatches
{
[HarmonyPatch(typeof(MooringSet))]
private static class MooringSetPatches
{
[HarmonyPatch("Awake")]
[HarmonyPostfix]
public static void MooringComponentPatch(MooringSet __instance)
{
((Component)((Component)__instance).transform.parent).gameObject.AddComponent<TowingSet>();
}
}
[HarmonyPatch(typeof(PickupableBoatMooringRope))]
private static class BoatMooringRopePatches
{
[HarmonyPatch("MoorTo")]
[HarmonyPostfix]
public static void MoorToPatch(PickupableBoatMooringRope __instance, GPButtonDockMooring mooring, Rigidbody ___boatRigidbody)
{
if (((Component)mooring).gameObject.CompareTag("Boat"))
{
TowingSet component = ((Component)___boatRigidbody).GetComponent<TowingSet>();
TowingSet componentInParent = ((Component)mooring).GetComponentInParent<TowingSet>();
if (componentInParent != null && (!component.towed || (Object)(object)componentInParent == (Object)(object)component.GetTowedBy()))
{
component.UpdateTowedBy();
componentInParent.UpdateTowedBoats();
}
}
}
[HarmonyPatch("ThrowRopeTo")]
[HarmonyPrefix]
public static bool ThrowRopeToPatch(PickupableBoatMooringRope __instance, GPButtonDockMooring mooring, Rigidbody ___boatRigidbody)
{
if (((Component)mooring).gameObject.CompareTag("Boat"))
{
if ((Object)(object)((Component)___boatRigidbody).transform != (Object)(object)((Component)((Component)mooring).GetComponentInParent<TowingSet>()).transform)
{
__instance.MoorTo(mooring);
}
return false;
}
return true;
}
[HarmonyPatch("Unmoor")]
[HarmonyPrefix]
public static void UnmoorPatch(SpringJoint ___mooredToSpring, ref TowingSet __state)
{
if ((Object)(object)___mooredToSpring != (Object)null)
{
TowingSet componentInParent = ((Component)___mooredToSpring).GetComponentInParent<TowingSet>();
if (componentInParent != null)
{
__state = componentInParent;
}
}
}
[HarmonyPatch("Unmoor")]
[HarmonyPostfix]
public static void UnmoorPostPatch(TowingSet __state, Rigidbody ___boatRigidbody)
{
if (Object.op_Implicit((Object)(object)__state))
{
__state.UpdateTowedBoats();
}
((Component)___boatRigidbody).GetComponent<TowingSet>().UpdateTowedBy();
}
}
[HarmonyPatch(typeof(BoatMooringRopes))]
private static class BoatMooringRopesPatches
{
[HarmonyPatch("UnmoorAllRopes")]
[HarmonyPostfix]
public static void UnmoorAllRopesPatch(BoatMooringRopes __instance)
{
TowingSet componentInParent = ((Component)__instance).GetComponentInParent<TowingSet>();
if (componentInParent == null || componentInParent.GetCleats() == null)
{
return;
}
GPButtonDockMooring[] cleats = componentInParent.GetCleats();
for (int i = 0; i < cleats.Length; i++)
{
PickupableBoatMooringRope componentInChildren = ((Component)cleats[i]).GetComponentInChildren<PickupableBoatMooringRope>();
if (componentInChildren != null)
{
componentInChildren.Unmoor();
componentInChildren.ResetRopePos();
}
}
}
}
}
[BepInPlugin("com.nandbrew.towableboats", "Towable Boats", "0.2.2")]
public class Plugin : BaseUnityPlugin
{
public const string PLUGIN_ID = "com.nandbrew.towableboats";
public const string PLUGIN_NAME = "Towable Boats";
public const string PLUGIN_VERSION = "0.2.2";
internal static ConfigEntry<int> performanceMode;
internal static ConfigEntry<bool> drag;
internal static ConfigEntry<bool> smallBoats;
internal static Plugin instance;
private void Awake()
{
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Expected O, but got Unknown
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Expected O, but got Unknown
instance = this;
Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "com.nandbrew.towableboats");
performanceMode = ((BaseUnityPlugin)this).Config.Bind<int>("Settings", "Performance mode", 1, new ConfigDescription("How many boats in the chain behind the current boat get full physics", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 5), new object[1]
{
new ConfigurationManagerAttributes
{
Order = 2
}
}));
drag = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Drag", false, new ConfigDescription("Allow boats to pull on the boat towing them (buggy)", (AcceptableValueBase)null, new object[1]
{
new ConfigurationManagerAttributes
{
IsAdvanced = true
}
}));
smallBoats = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Small boats can tow", true, new ConfigDescription("Add anchor points to small boats", (AcceptableValueBase)null, new object[1]
{
new ConfigurationManagerAttributes
{
IsAdvanced = false,
Order = 1
}
}));
AssetTools.LoadAssetBundles();
}
}
internal class SleepPatches
{
[HarmonyPatch(typeof(Sleep), "CurrentBoatIsMoored")]
private static class IsMooredPatch
{
[HarmonyPostfix]
public static void Postfix(ref bool __result)
{
if (Object.op_Implicit((Object)(object)GameState.currentBoat) && __result && ((Component)GameState.currentBoat).GetComponentInParent<TowingSet>().towed)
{
__result = false;
}
}
}
}
internal class TowingSet : MonoBehaviour
{
private TowingSet towedBy;
private List<TowingSet> towedBoats;
public bool towing;
public bool towed;
private GPButtonDockMooring[] cleats;
public bool smallBoat;
private BoatMooringRopes mooringRopes;
public List<TowingSet> GetTowedBoats()
{
return towedBoats;
}
public TowingSet GetTowedBy()
{
return towedBy;
}
public GPButtonDockMooring[] GetCleats()
{
return cleats;
}
private void Awake()
{
mooringRopes = ((Component)this).GetComponent<BoatMooringRopes>();
Transform val = ((Component)this).transform.Find("towing set");
if (val != null)
{
if ((Object)(object)((Component)val).GetComponent<BoatPartOption>() == (Object)null)
{
((Component)val).gameObject.SetActive(true);
}
cleats = ((Component)val).GetComponentsInChildren<GPButtonDockMooring>();
}
else
{
AddCleats();
}
}
private void FixedUpdate()
{
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_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)
if (GameState.justStarted)
{
UpdateTowedBoats();
UpdateTowedBy();
}
if (cleats == null)
{
return;
}
if (Plugin.drag.Value)
{
for (int i = 0; i < cleats.Length; i++)
{
if (Object.op_Implicit((Object)(object)((Component)((Component)cleats[i]).transform).GetComponentInChildren<PickupableBoatMooringRope>()))
{
Vector3 val = ((Joint)((Component)((Component)cleats[i]).transform).GetComponentInChildren<SpringJoint>()).currentForce;
if (((Component)((Joint)((Component)((Component)cleats[i]).transform).GetComponentInChildren<SpringJoint>()).connectedBody).gameObject.GetComponent<BoatPerformanceSwitcher>().performanceModeIsOn())
{
val /= 10f;
}
((Component)this).gameObject.GetComponent<Rigidbody>().AddForceAtPosition(val / 3f, ((Component)cleats[i]).transform.position, (ForceMode)0);
}
}
}
if (!smallBoat)
{
return;
}
GPButtonDockMooring[] array = cleats;
foreach (GPButtonDockMooring val2 in array)
{
if (!Plugin.smallBoats.Value)
{
PickupableBoatMooringRope componentInChildren = ((Component)val2).GetComponentInChildren<PickupableBoatMooringRope>();
if (componentInChildren != null)
{
componentInChildren.Unmoor();
componentInChildren.ResetRopePos();
}
}
((Component)val2).gameObject.SetActive(Plugin.smallBoats.Value);
}
}
public void UpdateTowedBoats()
{
towedBoats = new List<TowingSet>();
bool flag = false;
if (cleats != null)
{
for (int i = 0; i < cleats.Length; i++)
{
if ((Object)(object)((Component)((Component)cleats[i]).transform).GetComponentInChildren<PickupableBoatMooringRope>() != (Object)null)
{
towedBoats.Add(((Component)((Component)((Component)cleats[i]).transform).GetComponentInChildren<PickupableBoatMooringRope>().GetBoatRigidbody()).GetComponent<TowingSet>());
flag = true;
}
}
}
towing = flag;
}
public void UpdateTowedBy()
{
bool flag = false;
towedBy = null;
PickupableBoatMooringRope[] ropes = mooringRopes.ropes;
foreach (PickupableBoatMooringRope val in ropes)
{
if (val.IsMoored())
{
object value = Traverse.Create((object)val).Field("mooredToSpring").GetValue();
SpringJoint val2 = (SpringJoint)((value is SpringJoint) ? value : null);
if (val2 != null && ((Component)val2).gameObject.CompareTag("Boat"))
{
towedBy = ((Component)val2).GetComponentInParent<TowingSet>();
flag = true;
}
}
}
towed = flag;
}
public bool PhysicsMode()
{
if (towed && Plugin.performanceMode.Value > 0)
{
TowingSet towingSet = towedBy;
for (int i = 0; i < Plugin.performanceMode.Value; i++)
{
if ((Object)(object)((Component)towingSet).transform == (Object)(object)GameState.currentBoat || (Object)(object)((Component)towingSet).transform == (Object)(object)GameState.lastBoat)
{
return true;
}
if (!towingSet.towed)
{
break;
}
towingSet = towingSet.GetTowedBy();
}
}
if (towing)
{
List<TowingSet> list = towedBoats;
for (int j = 0; j < 10; j++)
{
bool flag = false;
foreach (TowingSet item in list)
{
if ((Object)(object)((Component)item).transform == (Object)(object)GameState.currentBoat || (Object)(object)((Component)item).transform == (Object)(object)GameState.lastBoat)
{
return true;
}
if (item.towing)
{
list = item.GetTowedBoats();
flag = true;
}
}
if (!flag)
{
break;
}
}
}
return false;
}
public void AddCleats()
{
if ((Object)(object)AssetTools.bundle == (Object)null)
{
AssetTools.LoadAssetBundles();
}
int sceneIndex = ((Component)this).gameObject.GetComponent<SaveableObject>().sceneIndex;
try
{
GameObject val;
switch (sceneIndex)
{
case 50:
val = AssetTools.bundle.LoadAsset<GameObject>("Assets/TowableBoats/towing set brig.prefab");
break;
case 20:
val = AssetTools.bundle.LoadAsset<GameObject>("Assets/TowableBoats/towing set sanbuq.prefab");
break;
case 80:
val = AssetTools.bundle.LoadAsset<GameObject>("Assets/TowableBoats/towing set junk.prefab");
break;
case 70:
val = AssetTools.bundle.LoadAsset<GameObject>("Assets/TowableBoats/towing set jong.prefab");
break;
case 40:
val = AssetTools.bundle.LoadAsset<GameObject>("Assets/TowableBoats/towing set cog.prefab");
smallBoat = true;
break;
case 10:
val = AssetTools.bundle.LoadAsset<GameObject>("Assets/TowableBoats/towing set dhow.prefab");
smallBoat = true;
break;
case 90:
val = AssetTools.bundle.LoadAsset<GameObject>("Assets/TowableBoats/towing set kakam.prefab");
smallBoat = true;
break;
default:
return;
}
GameObject val2 = Object.Instantiate<GameObject>(val, ((Component)this).transform, false);
((Object)val2).name = "towing set";
cleats = val2.GetComponentsInChildren<GPButtonDockMooring>();
}
catch
{
Debug.LogError((object)("TowableBoats: Couldn't load towing set for " + ((Object)this).name + "!!"));
}
}
}
public static class Util
{
public static object InvokePrivate(object obj, string name, object arg)
{
return AccessTools.Method(obj.GetType(), name, (Type[])null, (Type[])null).Invoke(obj, new object[1] { arg });
}
}